Sostieni AppuntiFacili con una piccola donazione su PayPal
Dona con PayPalAny real TypeScript project is split across multiple files. Modules are how those files share code with each other: a file exports the values, functions, classes, or types it wants to make available, and other files import them. TypeScript’s module system builds directly on top of JavaScript’s ES Modules (ESM) syntax, adding full type-checking across file boundaries.
There are two flavors of exports — named exports and a default export — and understanding the difference (and when to reach for each) is fundamental to organizing a codebase well.
A named export exposes a value under a specific, fixed name. A module can have as many named exports as it wants:
// math-utils.ts
export function add(x: number, y: number): number {
return x + y;
}
export const VALUE = 42;
Anything marked export becomes importable, by that exact name, from other files.
A module can also have a single default export — at most one per file:
// math-utils.ts (continued)
function test() {
return "test";
}
export default test;
TIP
Default export is convenient when a module has one clear “main” thing to offer (a component, a class, a single function). The importing file is free to name it however it likes, since there’s no fixed export name to match against.
Putting the whole file together:
// math-utils.ts
function test() {
return "test";
}
export function add(x: number, y: number): number {
return x + y;
}
export const VALUE = 42;
export default test;
To import one or more named exports, use curly braces and match the exact exported name:
// main.ts
import { add, VALUE } from "./math-utils";
console.log(add(1, 10)); // 11
console.log(VALUE); // 42
WARNING
Named imports must match the exported name exactly (you can rename locally with as, e.g. import { add as sum } from "./math-utils";, but the original export name still has to exist). Misspelling a named import is a compile error, not a silent undefined.
The default export can be imported under any local name you choose — that’s the whole point of it being “default” rather than named:
// main.ts (continued)
import Something from "./math-utils";
console.log(Something()); // "test"
Nothing forces the imported name to be test, Something, or anything related to the original name — the module only ever exposes one default, so there’s no ambiguity about which value you’re importing.
Combining a default import with named imports in the same statement is also valid:
import Something, { add, VALUE } from "./math-utils";
Instead of listing individual named exports, you can import everything a module exports as a single namespace object:
// main.ts
import * as MathUtils from "./math-utils";
console.log(MathUtils.add(2, 3)); // 5
console.log(MathUtils.VALUE); // 42
console.log(MathUtils.default()); // "test" — the default export becomes a `.default` property
This style is handy when a module exports many related utilities and you want to keep them grouped under one recognizable prefix, or when you want to avoid naming collisions between imports from different modules.
A module can also forward another module’s exports without importing them locally first — a re-export. This is common in “barrel” files that aggregate several modules into one entry point:
// index.ts
export * from "./math-utils";
export * from "./string-utils";
Consumers can now do import { add } from "./index"; without knowing that add actually lives in math-utils.ts. You can also re-export selectively:
// index.ts
export { add, VALUE } from "./math-utils";
INFO
export * from "./math-utils" re-exports every named export, but it does not forward a default export. To re-export a default as well, you need an explicit export { default } from "./math-utils"; (optionally renaming it, e.g. export { default as test } from "./math-utils";).
tsconfig.jsonThe import/export syntax you write is the same regardless of target environment, but how TypeScript compiles it down to actual JavaScript module code depends on the module and moduleResolution options in tsconfig.json (covered in the very first lesson of this section). Modern JavaScript runtimes (browsers, current Node.js versions) understand ESM natively, while older Node.js tooling historically relied on CommonJS (require/module.exports). Setting "module": "ESNext" or "module": "NodeNext" versus "module": "CommonJS" changes the emitted output — and can also affect small but important details like whether a default import needs interop handling. When in doubt, match the module/moduleResolution settings to whatever runtime or bundler is actually going to execute the compiled code.
How many default exports can a single TypeScript module have?
What must match exactly when importing a named export?
Why can `import Something from "./math-utils";` use any local name?
What does `import * as MathUtils from "./math-utils";` do?
Does `export * from "./math-utils";` forward the module's default export?
What tsconfig.json option primarily controls how import/export syntax is compiled to JavaScript (ESM vs CommonJS)?
Scenario: You are organizing a small utilities library with separate files for string helpers and math helpers, plus a single entry point for consumers.
Task:
string-utils.ts with two named exports: capitalize(s: string): string and slugify(s: string): string.math-utils.ts with named exports add, VALUE and a default export test, as shown in this lesson.index.ts that re-exports everything from both files using export * from "./string-utils"; and export * from "./math-utils";.main.ts that imports capitalize, add, and VALUE all from ./index (not from the original files directly), and confirm it type-checks and runs correctly.math-utils’s default export from index.ts (e.g. export { default as mathTest } from "./math-utils";) and import mathTest in main.ts.Learning objective: practice organizing named and default exports across multiple files and aggregating them through a barrel file with re-exports.
Scenario: You’re deciding between a namespace-style import and individual named imports for a module that exports a dozen small helper functions.
Task:
math-utils.ts module from this lesson and add three more named exports of your choice (e.g. subtract, multiply, divide).import * as MathUtils from "./math-utils"; and call the same four functions through the namespace object.math-utils.ts grew to twenty exports?Learning objective: compare named imports against namespace imports in practice and form an opinion on when each style is preferable.
Prenota una lezione