import and export

Files are Modules

A file with a top-level import or export is a module: its variables are private unless exported. Types are exported and imported exactly like values.

src/models/product.ts

export type Category = "electronics" | "books" | "fashion";

export interface Product {
  id: number;
  name: string;
  price: number;
  category: Category;
}

export const GST_RATE = 0.18;

export function priceWithGst(p: Product): number {
  return Math.round(p.price * (1 + GST_RATE));
}

src/index.ts

import { priceWithGst, type Product, GST_RATE as TAX } from "./models/product";
import * as productModel from "./models/product";

const kettle: Product = { id: 1, name: "Kettle", price: 1299, category: "electronics" };
console.log(priceWithGst(kettle), TAX, productModel.GST_RATE);

Importing Node.js Built-in Modules

Example

Built-in modules use the node: prefix and come fully typed from @types/node.

import { createHash, randomUUID } from "node:crypto";
import { EventEmitter } from "node:events";
import path from "node:path";

const hash = createHash("sha256").update("order:OD-1:1299").digest("hex");
console.log(hash.slice(0, 16));
console.log(path.posix.join("/uploads", "products", "42.png"));
console.log(randomUUID().length);

const bus = new EventEmitter();
bus.on("paid", (id: string) => console.log("paid event for", id));
bus.emit("paid", "OD-1");

Output

8e03f08aa864f005
/uploads/products/42.png
36
paid event for OD-1

Re-exporting (Barrel Files)

An index.ts that re-exports from several files is called a barrel. It gives other code one import path.

// src/models/index.ts
export * from "./product";
export * from "./order";
export { default as Cart } from "./cart";
export type { User } from "./user";

Note: Very large barrels can slow down bundlers and tests (everything gets loaded). Keep them small or import from the specific file.