Modules, Declaration Files & tsconfig Deep Dive
📖 Concept
Modules in TypeScript follow the ES Module standard (import/export). Understanding module resolution, declaration files, and tsconfig options is essential for production TypeScript.
Declaration files (.d.ts) describe the types for JavaScript code that doesn't have TypeScript types. They're how TypeScript understands npm packages written in JavaScript.
@types/ packages — The DefinitelyTyped repository provides community-maintained type declarations for thousands of JavaScript packages. Install with npm i -D @types/lodash.
Module augmentation lets you add types to existing modules — extending library types without modifying their source.
tsconfig.json is the central configuration for the TypeScript compiler. Key sections:
compilerOptions— How TS compiles your codeinclude/exclude— Which files to processreferences— Project references for monorepos
Critical tsconfig options:
strict: true— Enables all strict checks (ALWAYS use this)target— Which JS version to output (ES2022 is a safe modern default)module/moduleResolution— How imports are resolvedpaths— Custom import aliases (@/components)noUncheckedIndexedAccess— Arrays/objects may return undefined
🏠 Real-world analogy: Declaration files are like user manuals for tools you didn't build. You don't have the blueprints (source code), but the manual (d.ts) tells you what buttons to press (API types). tsconfig.json is like the settings panel for your car — target speed, safety features, navigation mode.
💻 Code Example
1// ES Module syntax (TypeScript follows this standard)2// math.ts3export function add(a: number, b: number): number {4 return a + b;5}6export const PI = 3.14159;7export default class Calculator { /* ... */ }89// app.ts10// import Calculator, { add, PI } from "./math";1112// Type-only imports (erased at compile time)13// import type { User } from "./types";14// import { type User, createUser } from "./users";1516// Declaration files (.d.ts) — type definitions for JS code17// utils.d.ts18// declare function formatCurrency(amount: number, currency: string): string;19// declare const API_URL: string;20// declare module "untyped-lib" {21// export function doSomething(input: string): number;22// }2324// Module augmentation — extend existing types25// Extending Express Request (common pattern)26// declare module "express" {27// interface Request {28// user?: { id: string; role: string };29// }30// }3132// Global augmentation33// declare global {34// interface Window {35// analytics: { track(event: string): void };36// }37// }3839// Path aliases (in tsconfig: "paths": { "@/*": ["./src/*"] })40// import { UserService } from "@/services/user";41// import { Button } from "@/components/Button";4243// Ambient modules — declare types for non-TS files44// declare module "*.css" {45// const classes: Record<string, string>;46// export default classes;47// }48// declare module "*.svg" {49// import { FC, SVGProps } from "react";50// const SVG: FC<SVGProps<SVGSVGElement>>;51// export default SVG;52// }5354// Namespace (legacy — prefer ES modules)55// namespace Utils {56// export function log(msg: string) { console.log(msg); }57// export function warn(msg: string) { console.warn(msg); }58// }59// Utils.log("hello");6061// tsconfig.json — production-grade configuration:62// {63// "compilerOptions": {64// "target": "ES2022",65// "module": "ESNext",66// "moduleResolution": "bundler",67// "strict": true,68// "noUncheckedIndexedAccess": true,69// "noUnusedLocals": true,70// "noUnusedParameters": true,71// "noFallthroughCasesInSwitch": true,72// "forceConsistentCasingInFileNames": true,73// "esModuleInterop": true,74// "skipLibCheck": true,75// "declaration": true,76// "declarationMap": true,77// "sourceMap": true,78// "outDir": "./dist",79// "rootDir": "./src",80// "paths": { "@/*": ["./src/*"] }81// },82// "include": ["src/**/*"],83// "exclude": ["node_modules", "dist"]84// }8586// Example: tsconfig for a Next.js project:87// "compilerOptions": {88// "lib": ["dom", "dom.iterable", "esnext"],89// "jsx": "preserve",90// "incremental": true,91// "plugins": [{ "name": "next" }]92// }93console.log("Modules and tsconfig are the backbone of any TS project.");
🏋️ Practice Exercise
Mini Exercise:
- Create a
.d.tsdeclaration file for an imaginary JavaScript utility library - Set up path aliases in tsconfig and use them in imports
- Use module augmentation to add a custom property to Express
Request - Create a tsconfig with
strict: trueand all recommended options - Write ambient module declarations for
.cssand.svgimports
⚠️ Common Mistakes
Not installing
@types/packages for JavaScript libraries — TypeScript won't know the types; install@types/express,@types/node, etc.Confusing
moduleandmoduleResolutionin tsconfig —moduleis the output format;moduleResolutionis how TS finds imported filesUsing
namespacein new code — namespaces are legacy; ES modules (import/export) are the standard way to organize codeNot enabling
skipLibCheck: true— checking ALL declaration files in node_modules is slow and finds irrelevant errorsForgetting that
.d.tsfiles are type-only — they cannot contain any implementation, only type declarations
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Modules, Declaration Files & tsconfig Deep Dive