TypeScript Cheatsheet
Modules
Use this TypeScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
ES Module Syntax
// Named export export const PI = 3.14159; export function add(a: number, b: number): number { return a + b; } export class Logger { log(msg: string) { console.log(msg); } } export interface Config { port: number; } export type UserId = string; // Default export (only one per file) export default function greet(name: string): string { return `Hello, ${name}`; } // Export list (rename with `as`) const x = 1; const y = 2; export { x, y }; export { x as xVal, y as yVal };
Import Syntax
// Named import import { add, Logger } from "./utils"; // Rename on import import { add as sum, Logger as Log } from "./utils"; // Default import import greet from "./greet"; // Default + named import greet, { PI, Logger } from "./module"; // Namespace import — all exports under one object import * as MathUtils from "./math"; MathUtils.add(1, 2); MathUtils.PI; // Side-effect only import import "./polyfill"; // Type-only import (stripped at compile time — no runtime import) import type { User } from "./types"; import type { Config, UserId } from "./config";
Type-Only Imports and Exports
// import type — guarantees erasure at emit; preferred when importing only types import type { User, Config } from "./types"; import type { EventEmitter } from "events"; // export type — export a type (not a value) export type { User }; export type { Config as AppConfig }; // Inline type modifier (TS 4.5+) — mix type and value imports import { type User, createUser } from "./user"; // Why use import type? // - Avoids circular dependency issues // - Required for --isolatedModules // - Clearer intent // - Eliminated entirely by bundlers (no runtime cost)
Re-Exporting
// Re-export all named exports export * from "./math"; // Re-export and rename export { add as sum } from "./math"; // Re-export default as named export { default as greet } from "./greet"; // Re-export with type export type { User } from "./types"; // Barrel file pattern (index.ts) export * from "./user"; export * from "./post"; export * from "./comment"; export { default as App } from "./App";
Module Resolution
// Relative paths — resolved relative to current file import "./sibling"; import "../parent/module"; import "../../deep/module"; // Non-relative — resolved via node_modules or paths config import express from "express"; import { z } from "zod"; // tsconfig.json path aliases // "paths": { "@/*": ["./src/*"] } import { Button } from "@/components/Button"; // tsconfig.json baseUrl // "baseUrl": "./src" import { helper } from "utils/helper"; // resolves to src/utils/helper.ts // Module resolution strategies // "moduleResolution": "NodeNext" — for Node ESM (requires .js extension) // "moduleResolution": "bundler" — for bundlers (Vite, webpack; no extension required) // "moduleResolution": "node" — classic CommonJS (legacy)
CommonJS Interop
// Importing CJS default export (with esModuleInterop: true) import fs from "fs"; import path from "path"; // Without esModuleInterop import * as fs from "fs"; // require() — available in Node CJS context const data = require("./data.json"); // module.exports — CJS style output // In .ts files, prefer ES module syntax; the compiler handles the output // Explicit CJS interop helpers (rarely needed) import { createRequire } from "module"; const require = createRequire(import.meta.url); const pkg = require("./package.json");
Dynamic Imports
// import() — returns Promise<module>; always async const module = await import("./heavy-module"); module.doSomething(); // With type annotation const { format } = await import("./formatter") as { format: (s: string) => string }; // Conditional loading async function loadFeature(flag: boolean) { if (flag) { const { Feature } = await import("./Feature"); return new Feature(); } } // Dynamic import in non-async context import("./logger").then(({ Logger }) => { const log = new Logger(); log.info("Loaded"); }); // Code splitting (webpack/bundler hint) const LazyComponent = React.lazy(() => import("./LazyComponent"));
Ambient Module Declarations
// Declare a module shape for untyped JS packages declare module "untyped-package" { export function doThing(x: string): number; export const version: string; export default class Thing { constructor(opts: Record<string, unknown>); run(): void; } } // Wildcard module declarations (e.g., for file imports) declare module "*.svg" { const content: string; export default content; } declare module "*.png" { const src: string; export default src; } declare module "*.json" { const value: unknown; export default value; } // CSS modules declare module "*.module.css" { const styles: { readonly [key: string]: string }; export default styles; }
Declaration Files (.d.ts)
// lib.d.ts — ships with TypeScript; declares built-in globals // yourlib.d.ts — declare types for a JS library export declare function parse(input: string): number; export declare class Parser { constructor(options?: ParserOptions); parse(input: string): AST; } export declare interface ParserOptions { strict?: boolean; encoding?: BufferEncoding; } // global augmentation in .d.ts declare global { interface Window { myLib: { version: string }; } var __DEV__: boolean; } export {}; // Needed to make this a module (not a script)
Module Augmentation
// Augment a third-party module's types import "express"; declare module "express" { interface Request { user?: { id: string; role: string }; sessionId?: string; } } // Augment built-in types declare global { interface Array<T> { last(): T | undefined; } } Array.prototype.last = function() { return this[this.length - 1]; }; // Augment a class (rarely needed) declare module "./MyClass" { interface MyClass { extraMethod(): void; } }
Namespaces (Legacy)
// Namespaces group related declarations (prefer ES modules) namespace Validation { export interface StringValidator { isAcceptable(s: string): boolean; } export class LettersOnlyValidator implements StringValidator { isAcceptable(s: string): boolean { return /^[A-Za-z]+$/.test(s); } } } const v: Validation.StringValidator = new Validation.LettersOnlyValidator(); // Nested namespace namespace Shapes { export namespace Polygons { export class Triangle {} export class Square {} } } const t = new Shapes.Polygons.Triangle(); // Merging namespace with a function function buildLabel(name: string): string { return buildLabel.prefix + name + buildLabel.suffix; } namespace buildLabel { export let suffix = ""; export let prefix = "Hello, "; }
import.meta (ESM)
// Available in ESM context import.meta.url; // current file URL import.meta.env; // Vite / bundler env vars import.meta.env.MODE; // "development" | "production" import.meta.env.VITE_API; // user-defined env var // Node.js import.meta.dirname; // Node 21.2+ (equivalent of __dirname) import.meta.filename; // Node 21.2+ (equivalent of __filename) import.meta.resolve("./dep"); // resolve relative to current file
Triple-Slash References (Legacy)
/// <reference path="./other-file.ts" /> // explicit dependency /// <reference types="node" /> // include @types/node /// <reference lib="ES2022" /> // include lib file /// <reference no-default-lib="true" /> // opt out of default libs // Modern alternative: just use tsconfig.json // { "compilerOptions": { "types": ["node"], "lib": ["ES2022", "DOM"] } }
Exports and Module Format Notes
// package.json "exports" field (Node.js / bundlers) // { // "exports": { // ".": { // "import": "./dist/index.mjs", // "require": "./dist/index.cjs", // "types": "./dist/index.d.ts" // } // } // } // TypeScript 4.7+ — .mts and .cts file extensions // .mts → emits .mjs (ESM) // .cts → emits .cjs (CJS) // .ts → respects "module" in tsconfig // Verbatim module syntax (TS 5.0+) // "verbatimModuleSyntax": true // Forces: type-only imports must use `import type`; each import is emitted as-is