TypeScript Tooling

tsconfig, strict & Declarations

TypeScript is a compiler as much as a language. Its configuration, strictness flags, and declaration files determine how much safety you actually get.

TypeScript 5 3 Topics
01

tsconfig.json & strict Mode

tsconfig.json configures the compiler. The single most important setting is "strict": true, which turns on the full suite of type-safety checks. Without it, TypeScript is far more permissive than most people expect.

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",        // JS version to emit
    "module": "ESNext",        // module system
    "strict": true,            // enable all strict checks (do this)
    "noUncheckedIndexedAccess": true,  // arr[i] is T | undefined
    "esModuleInterop": true,
    "outDir": "./dist",
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}
strict: true bundles strictNullChecks, noImplicitAny, strictFunctionTypes, and more. It's the difference between "types as documentation" and "types that actually catch bugs". Always start a project with it on.
02

Modules & the Compile Pipeline

TypeScript uses ES module import/export, plus a type-only import form. The compiler (tsc) type-checks and emits JavaScript; in most projects a bundler (Vite, esbuild) handles the actual build for speed.

TypeScript — Imports & Compiling
// value + type imports
import { createUser } from "./users";
import type { User } from "./types";   // erased entirely at build

export function greet(u: User) { return `Hi ${u.name}`; }

# compile the whole project per tsconfig.json
# tsc

# type-check only, emit nothing (great for CI)
# tsc --noEmit
import type makes it explicit that an import is only a type and will be stripped from the output. It avoids accidental runtime dependencies and can speed up builds. Pair with "verbatimModuleSyntax" for strict enforcement.
03

Declaration Files (.d.ts)

A declaration file (.d.ts) describes the types of JavaScript code without any implementation. It's how untyped JS libraries get TypeScript support, and how your compiled library ships its types to consumers.

math.d.ts
// describes the shape of a JS module — no implementation
declare function add(a: number, b: number): number;
declare const PI: number;
export { add, PI };

Most popular libraries ship their own types or have community types on DefinitelyTyped, installed via @types/* packages.

Built-in types
Modern libraries (Vite, Zod, Prisma) ship .d.ts files in the package itself.
@types/* packages
Community types from DefinitelyTyped, e.g. npm i -D @types/node.
tsc --declaration
Generates .d.ts for your own library so consumers get full typing.
If an import shows "Could not find a declaration file for module 'x'", install @types/x, or if none exists, add a declare module "x"; stub. Never reach for // @ts-ignore as a first resort.

Quick Quiz

1. The most important tsconfig setting for safety is…
2. import type { User } is…
3. A .d.ts file contains…
4. tsc --noEmit does what?
5. Community types for untyped JS libs live on…