0
0
Typescriptprogramming~15 mins

Import syntax variations in Typescript - Deep Dive

Choose your learning style9 modes available
Overview - Import syntax variations
What is it?
Import syntax variations in TypeScript are different ways to bring code from one file or module into another. This lets you use functions, classes, or variables defined elsewhere without rewriting them. There are several styles of import depending on what you want to use and how the original code is organized. Understanding these helps you organize your code better and reuse it efficiently.
Why it matters
Without import syntax, every file would need to repeat the same code, making programs large and hard to maintain. Importing allows sharing and reusing code easily, which saves time and reduces mistakes. It also helps split big projects into smaller, manageable pieces. Without imports, collaboration and scaling software would be much harder.
Where it fits
Before learning import syntax, you should know basic TypeScript syntax and how modules work conceptually. After mastering imports, you can learn about module resolution, dynamic imports, and advanced bundling techniques. This topic is a foundation for working with modern TypeScript projects and libraries.
Mental Model
Core Idea
Import syntax is the way to bring pieces of code from one place into another so you can use them without copying.
Think of it like...
It's like borrowing a book from a library instead of buying your own copy; you get access to the content without owning it permanently.
┌─────────────┐       ┌─────────────┐
│  Module A   │       │  Module B   │
│ (exports)   │──────▶│ (imports)   │
└─────────────┘       └─────────────┘

Different arrows show different import styles:
- Named import: import { item } from 'Module A'
- Default import: import item from 'Module A'
- Namespace import: import * as alias from 'Module A'
Build-Up - 7 Steps
1
FoundationBasic named imports
🤔
Concept: Learn how to import specific named exports from a module.
If a module exports multiple things by name, you can import just what you need using curly braces. Example: // mathUtils.ts export function add(a: number, b: number) { return a + b; } export function subtract(a: number, b: number) { return a - b; } // main.ts import { add } from './mathUtils'; console.log(add(2, 3));
Result
5
Understanding named imports lets you pick only the parts of code you need, keeping your code clean and efficient.
2
FoundationDefault imports explained
🤔
Concept: Learn how to import the default export from a module without curly braces.
Modules can export one main thing as default. You import it without braces and can name it whatever you want. Example: // logger.ts export default function log(message: string) { console.log(message); } // main.ts import log from './logger'; log('Hello!');
Result
Hello!
Default imports provide a simple way to import the main feature of a module with flexible naming.
3
IntermediateImporting everything as namespace
🤔Before reading on: do you think importing everything as a namespace creates copies or references? Commit to your answer.
Concept: Learn how to import all exports under a single alias using * as syntax.
Sometimes you want to access many exports from a module without importing each one separately. You can import the whole module as an object. Example: // mathUtils.ts export function add(a: number, b: number) { return a + b; } export function subtract(a: number, b: number) { return a - b; } // main.ts import * as math from './mathUtils'; console.log(math.add(5, 7));
Result
12
Knowing namespace imports helps when you want to group related functions or variables under one name for clarity.
4
IntermediateRenaming imports with 'as'
🤔Before reading on: do you think renaming imports changes the original export name? Commit to your answer.
Concept: Learn how to rename imports to avoid name conflicts or improve clarity.
You can rename imported items using the 'as' keyword to avoid clashes or make names clearer. Example: // shapes.ts export function circle() {} export function square() {} // main.ts import { circle as drawCircle } from './shapes'; drawCircle();
Result
No output but function drawCircle is called
Renaming imports allows flexible naming in your code without changing the original module.
5
IntermediateCombining default and named imports
🤔
Concept: Learn how to import both default and named exports from the same module in one statement.
Modules can have a default export plus named exports. You can import both together. Example: // user.ts export default class User {} export function getUserName() { return 'Alice'; } // main.ts import User, { getUserName } from './user'; const user = new User(); console.log(getUserName());
Result
Alice
Combining imports keeps your code concise and organized when using multiple exports from one module.
6
AdvancedDynamic imports with import()
🤔Before reading on: do you think dynamic imports load modules immediately or only when needed? Commit to your answer.
Concept: Learn how to load modules dynamically at runtime using import() function.
Dynamic imports let you load modules only when you need them, which can improve performance. Example: async function loadModule() { const math = await import('./mathUtils'); console.log(math.add(10, 20)); } loadModule();
Result
30
Understanding dynamic imports helps optimize app loading by delaying code loading until necessary.
7
ExpertImport type-only syntax
🤔Before reading on: do you think importing types affects the JavaScript output? Commit to your answer.
Concept: Learn how to import only types without including code in the final JavaScript output.
TypeScript allows importing types with 'import type' to avoid runtime code inclusion. Example: // types.ts export interface User { name: string; } // main.ts import type { User } from './types'; function greet(user: User) { console.log(user.name); }
Result
No JavaScript code generated for the import, only type checking happens
Knowing type-only imports prevents unnecessary code in output and improves build size and speed.
Under the Hood
TypeScript import statements are compiled to JavaScript import or require calls depending on the module system. Named imports correspond to properties on the exported object, default imports map to the module's default export. Namespace imports create an object containing all exports. Dynamic imports use promises to load modules asynchronously. Type-only imports are erased during compilation and do not produce runtime code.
Why designed this way?
The import syntax follows the ECMAScript module standard to ensure compatibility across JavaScript environments. TypeScript extends this with type-only imports to separate type information from runtime code, improving performance. Dynamic imports were added to support code splitting and lazy loading, which are important for large applications.
┌───────────────┐       ┌───────────────┐
│ Module Source │──────▶│ Import Syntax │
│ (exports)     │       │ (named, default, namespace, dynamic, type-only)
└───────────────┘       └───────────────┘
          │                        │
          ▼                        ▼
  ┌─────────────────┐      ┌─────────────────┐
  │ Compiled JS Code │◀─────│ TypeScript Compiler │
  └─────────────────┘      └─────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does renaming an import change the original export name? Commit yes or no.
Common Belief:Renaming an import with 'as' changes the original export in the source module.
Tap to reveal reality
Reality:Renaming only changes the local name in your file; the original export remains unchanged.
Why it matters:Thinking renaming changes the source can cause confusion and errors when collaborating or debugging.
Quick: Do default imports always mean the module exports a single function or class? Commit yes or no.
Common Belief:A default export means the module only exports one thing, usually a function or class.
Tap to reveal reality
Reality:A module can have a default export plus many named exports; default is just a special export.
Why it matters:Misunderstanding this limits how you use modules and can cause import errors.
Quick: Does importing types with 'import type' add code to the final JavaScript? Commit yes or no.
Common Belief:All imports, including types, add code to the JavaScript output.
Tap to reveal reality
Reality:Type-only imports are erased during compilation and do not produce runtime code.
Why it matters:Not knowing this can lead to unnecessarily large bundles or confusion about code size.
Quick: Does namespace import create copies of all exports? Commit yes or no.
Common Belief:Importing everything as a namespace copies all exports into a new object.
Tap to reveal reality
Reality:Namespace import creates a reference object to the exports, not copies, preserving memory and consistency.
Why it matters:Believing it copies can lead to inefficient code or misunderstanding of module behavior.
Expert Zone
1
Type-only imports improve build performance by preventing unnecessary code inclusion, especially in large projects.
2
Dynamic imports return promises, enabling asynchronous module loading and better control over app performance.
3
Combining default and named imports in one statement is syntactic sugar but helps keep import statements concise and readable.
When NOT to use
Avoid using namespace imports when you only need a few exports to reduce code size and improve tree shaking. Do not use dynamic imports for modules needed immediately at startup to prevent delays. Avoid default exports in libraries where named exports improve clarity and refactoring safety.
Production Patterns
In production, developers use named imports for precise control and better tree shaking. Dynamic imports are common for lazy loading features or large dependencies. Type-only imports are widely used in TypeScript libraries to separate types from runtime code, improving bundle size.
Connections
Modular programming
Import syntax is a practical implementation of modular programming principles.
Understanding import syntax deepens comprehension of how modular design breaks programs into reusable parts.
Lazy loading in web development
Dynamic imports enable lazy loading, a technique to load code only when needed.
Knowing import variations helps grasp how web apps optimize performance by loading resources on demand.
Library borrowing systems
Importing code is like borrowing books from a library, sharing resources without duplication.
This cross-domain connection highlights resource sharing and reuse concepts common in software and everyday life.
Common Pitfalls
#1Importing a named export without curly braces.
Wrong approach:import add from './mathUtils'; // mathUtils exports add as named export
Correct approach:import { add } from './mathUtils';
Root cause:Confusing default exports with named exports leads to syntax errors or undefined imports.
#2Using 'import type' for runtime values.
Wrong approach:import type { add } from './mathUtils'; console.log(add(1,2));
Correct approach:import { add } from './mathUtils'; console.log(add(1,2));
Root cause:Misunderstanding that 'import type' only imports types and cannot be used for runtime code.
#3Assuming dynamic imports are synchronous.
Wrong approach:const math = import('./mathUtils'); console.log(math.add(1,2)); // Error: math is a Promise
Correct approach:import('./mathUtils').then(math => console.log(math.add(1,2)));
Root cause:Not recognizing that dynamic imports return promises and require async handling.
Key Takeaways
Import syntax variations let you bring code from other files in different ways to suit your needs.
Named imports pick specific exports, default imports bring the main export, and namespace imports group all exports.
Dynamic imports load modules only when needed, improving app performance through lazy loading.
Type-only imports in TypeScript import just types without adding runtime code, keeping bundles small.
Understanding these variations helps write cleaner, more efficient, and maintainable TypeScript code.