📖 Scenario: You are building a TypeScript app that loads different greeting messages dynamically based on user choice. Each greeting is in a separate module.
🎯 Goal: Create a TypeScript program that dynamically imports greeting modules with proper type annotations and displays the greeting message.
📋 What You'll Learn
Create a type for the greeting module's default export
Use dynamic import() with type annotations
Load a greeting module dynamically based on a variable
Print the greeting message from the imported module
💡 Why This Matters
🌍 Real World
Dynamic imports let apps load code only when needed, saving resources and speeding up startup.
💼 Career
Many modern web apps use dynamic imports with TypeScript to improve performance and maintain type safety.
Progress0 / 4 steps
1
Create greeting modules and type
Create a type called GreetingModule with a default string property. Then create two modules: hello.ts exporting default as "Hello, world!" and hi.ts exporting default as "Hi there!".
Typescript
Hint
Use export type GreetingModule = { default: string }; and create two files with export default strings.
2
Add a variable for the module name
Create a variable called moduleName and set it to the string "hello".
Typescript
Hint
Use const moduleName = "hello"; to store the module name.
3
Dynamically import the module with type
Use import() with a type annotation to dynamically import the module named by moduleName. Store the result in a variable called greetingModule with type Promise<typeof import("./hello")>.
Typescript
Hint
Use const greetingModule: Promise<typeof import("./hello")> = import(`./${moduleName}`); to dynamically import with types.
4
Print the greeting message
Use await to get the module from greetingModule and then print the default export using console.log. Wrap the code in an async function called showGreeting and call it.
Typescript
Hint
Use an async function to await the import and then console.log(mod.default).
Practice
(1/5)
1. What is the main benefit of using dynamic imports with types in TypeScript?
easy
A. They make the code run faster by compiling to machine code.
B. They load modules only when needed, improving app speed and type safety.
C. They automatically convert JavaScript to TypeScript.
D. They prevent any runtime errors without writing tests.
Solution
Step 1: Understand dynamic imports
Dynamic imports load code only when it is needed, not all at once.
Step 2: Understand types with dynamic imports
Using typeof import() adds type safety, helping catch errors early.
Final Answer:
They load modules only when needed, improving app speed and type safety. -> Option B
Quick Check:
Dynamic imports + types = faster and safer code [OK]
A. Type annotation is incorrect; should not use typeof import().
B. Cannot call console.log inside async code.
C. Missing 'await' before import, so mod is a Promise, not the module.
D. Module './utils' does not exist.
Solution
Step 1: Check import usage
Dynamic import returns a Promise, so it must be awaited to get the module.
Step 2: Identify error cause
Without await, mod is a Promise, so calling mod.helper() causes an error.
Final Answer:
Missing 'await' before import, so mod is a Promise, not the module. -> Option C
Quick Check:
Dynamic import needs await to get module [OK]
Hint: Always await dynamic imports to get the module object [OK]
Common Mistakes:
Forgetting to await dynamic import
Misusing type annotation syntax
Assuming import returns module directly
5. You want to dynamically import a module './config' that exports a default object with a property apiUrl. How do you correctly type and access apiUrl using dynamic imports in TypeScript?
hard
A. const config: typeof import('./config') = await import('./config'); console.log(config.default.apiUrl);
B. const config = await import('./config'); console.log(config.apiUrl);
C. const config: typeof import('./config') = await import('./config'); console.log(config.apiUrl);
D. const config = await import('./config'); console.log(config.default.apiUrl);
Solution
Step 1: Understand default exports in dynamic imports
When a module exports default, it is accessed via the default property on the imported module object.
Step 2: Use type annotation and access property
Typing with typeof import() is correct, and to get apiUrl, use config.default.apiUrl.