TypeScript Strict Mode

Master TypeScript strict mode flags to eliminate null exceptions, untyped variables, and unsafe runtime method invocations.

TL;DR

  1. Enable strict mode in compiler options for complete type safety.
  2. Prevent runtime null pointer crashes using strict strictNullChecks validation.
  3. Migrate legacy codebases incrementally by enabling individual compilerOptions flags.

Strict Mode Flags

    Enable all strict flags

    Turn on complete strict compiler checking.

    {
      "compilerOptions": {
        "strict": true
      }
    }
    Individual flag migration

    Activate specific strict checks progressively.

    {
      "compilerOptions": {
        "strict": false,
        "noImplicitAny": true,
        "strictNullChecks": true
      }
    }
    Prevent emit on errors

    Block build output if type errors exist.

    {
      "compilerOptions": {
        "strict": true,
        "noEmitOnError": true
      }
    }

Resolving Implicit Any

    Annotate function params

    Supply explicit parameter and return types.

    // Error under noImplicitAny:
    // function add(a, b) { return a + b; }
    function add(a: number, b: number): number {
      return a + b;
    }
    Typed event listeners

    Annotate callback event arguments.

    const btn = document.querySelector("button");
    btn?.addEventListener("click", (e: MouseEvent) => {
      console.log(e.clientX);
    });
    Typed JSON parsing

    Type parsed objects via unknown narrowing.

    const raw = '{"id": 1, "name": "Ada"}';
    const data: unknown = JSON.parse(raw);
    if (typeof data === "object" && data !== null) {
      console.log("Valid parsed object");
    }
    Generic array typing

    Provide explicit element types for empty arrays.

    // Avoid: const items = [];
    const items: string[] = [];
    items.push("alpha");

Strict Null Safety

    Explicit nullable types

    Include null in variable union declarations.

    // Error under strictNullChecks:
    // const user: string = null;
    const user: string | null = null;
    Optional chaining access

    Safely navigate nested nullable structures.

    type Profile = { address?: { city?: string } };
    function getCity(p?: Profile): string {
      return p?.address?.city ?? "Unknown";
    }
    Type guard narrowing

    Check existence before invoking methods.

    function format(val: string | null): string {
      if (val === null) {
        return "N/A";
      }
      return val.toUpperCase();
    }
    Array find safety

    Handle undefined results from array lookups.

    const nums = [10, 20, 30];
    const found = nums.find(n => n > 15);
    if (found !== undefined) {
      console.log(found * 2);
    }

Class Property Initialization

    Constructor assignment

    Assign properties directly in constructors.

    class Account {
      id: string;
      constructor(id: string) {
        this.id = id;
      }
    }
    Inline default assignment

    Provide initial values directly at declaration.

    class RetryPolicy {
      maxAttempts: number = 3;
      delayMs: number = 1000;
    }
    Parameter properties

    Declare and initialize members in constructor.

    class UserSession {
      constructor(
        public readonly token: string,
        public expiresAt: number
      ) {}
    }
    Definite assignment assertion

    Mark fields initialized by DI frameworks.

    class ViewComponent {
      // Initialized by framework lifecycle:
      container!: HTMLElement;
    }

Strict Function and Method Rules

    Strict function types

    Ensure contravariant function parameters.

    type Handler = (e: MouseEvent) => void;
    // Error: assigning broader event callbacks
    // is disallowed under strictFunctionTypes
    No implicit this

    Disallow unqualified this references.

    interface Counter {
      count: number;
      increment(this: Counter): void;
    }
    Strict bind call apply

    Type check function invocation arguments.

    function greet(g: string, n: string): void {
      console.log(`${g}, ${n}`);
    }
    greet.call(undefined, "Hello", "Ada");
    No unchecked index access

    Treat dictionary lookup results as undefined.

    type Scores = Record<string, number>;
    const table: Scores = { math: 95 };
    const score: number | undefined = table["sci"];

Tips

  1. Enable strictNullChecks first during gradual migrations, as it resolves the vast majority of silent JavaScript runtime bugs.
  2. Use unknown rather than disabling noImplicitAny when dealing with uncertain dynamic API payloads to preserve rigorous type narrowing.

Warnings

  1. Never bypass strictPropertyInitialization with non-null assertion operators unless external dependency injection or lifecycle hooks guarantee immediate value population.
  2. Toggling strict mode in large existing projects without progressive milestones can cause hundreds of immediate compile failures across modules.

In Practice

FAQ