Core Concepts

2 min read
Rapid overview

TypeScript Core Concepts

Layer TypeScript on top of solid JavaScript fundamentals. Focus on strict typing, modeling real-world data, and catching errors early.

Project setup

  • Strict mode: Enable strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes, noUncheckedIndexedAccess for predictable behavior.
  • Module resolution: Prefer ESM (module: esnext), set moduleResolution to bundler/node16 depending on toolchain, and configure paths for imports.
  • Emit: Keep noEmit for type-check-only projects or target ES2022+ with bundlers handling transpilation.

Type system building blocks

  • Unions/intersections: Compose shapes (type Result = Success | Failure). Use discriminated unions for runtime safety.
  • Literals and enums: Prefer literal unions over enums when possible for tree shaking and type inference.
  • Tuples: Model fixed-length ordered data (e.g., [status, data]).
  • any vs unknown vs never: Default to unknown for untrusted data; use never for exhaustiveness; avoid any except at boundaries.

Functions and generics

  • Function types: Type params and return values explicitly. Use overloads for ergonomic call sites and narrow implementations.
  • Generics: Constrain (<T extends ...>) to enable safe access; combine with utility types (Partial, Pick, Omit, Record, ReturnType).
  • Conditional/mapped types: Transform shapes (Readonly<T>, NonNullable<T>, custom DeepPartial).

Narrowing and control flow analysis

  • Type guards: typeof, instanceof, discriminants, custom predicates (value is Foo).
  • Nullish checks: value != null for null/undefined, ?? for defaults.
  • Exhaustiveness: switch + never fallthrough checks; handle default intentionally.

Async and errors

  • Promise shapes: Type Promise<Result<T>>, avoid Promise<any>. Use Awaited<T> to unwrap.
  • Errors: Treat unknown in catch; narrow with instanceof Error or custom guards.
  • Interop: Provide types for fetch responses, third-party libs, and JSON.parse output via schemas or zod/io-ts.

Tooling and testing

  • Linting: ESLint with @typescript-eslint rules; forbid implicit any, unused vars, and unhandled promises.
  • Builds: Vite/tsup/esbuild for apps/libs; emit types with tsc -p tsconfig.build.json when publishing packages.
  • DX tips: Enable incremental/composite for large projects; use tsc --noEmit in CI.

Interview-ready patterns

  • Implement Result/Option types and helpers.
  • Write a type-safe fetch wrapper that enforces response decoding.
  • Model a React component prop type with discriminated unions and shared base props.
  • Express recursive types for tree data and ensure depth-safe usage.