← Debugging Guides

阅读中文版本

TypeScript TS2564 — Property Has No Initializer

Fix TS2564 by initializing class fields, using definite assignment assertions only when safe, or assigning in the constructor.

intermediatedebuggingtypescriptstrictclasses

Symptoms

  • error TS2564: Property 'name' has no initializer and is not definitely assigned
  • The error appeared after enabling strictPropertyInitialization
  • A property is set only in an async init method

Possible causes

  • The field is declared without a default and not assigned in the constructor
  • The value is initialized in a separate lifecycle method the compiler cannot see
  • A DI framework assigns the field, so TypeScript cannot prove assignment

Diagnosis steps

Read the exact property name

npx tsc --noEmit 2>&1 | grep TS2564

Interpretation

The message names the property, telling you where an initializer or assignment belongs.

Pick the right fix

grep -n "constructor" src/*.ts | head

Interpretation

Assign in the constructor when the value is known there; use a definite assignment assertion only when initialization is guaranteed elsewhere.

Root cause

strictPropertyInitialization requires every declared property to be assigned before the constructor returns. Fields assigned only in a later method, or by external code, are flagged as not definitely assigned.

Fix

Initialize at declaration, assign in the constructor, mark required injected fields with the definite assignment assertion `!` and document why, or model the property as optional when it can be absent.

Risk note

The `!` assertion disables the check entirely; a genuinely unset property then becomes undefined at runtime.

Verify the fix

Run tsc --noEmit and confirm TS2564 is gone; a test constructs the object and asserts the property is set.

Symptoms

This debugging guide addresses “TypeScript TS2564 — Property Has No Initializer”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.

Observed symptoms include:

  • error TS2564: Property ‘name’ has no initializer and is not definitely assigned
  • The error appeared after enabling strictPropertyInitialization
  • A property is set only in an async init method

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Read the exact property name

npx tsc --noEmit 2>&1 | grep TS2564

The message names the property, telling you where an initializer or assignment belongs.

Step 2: Pick the right fix

grep -n "constructor" src/*.ts | head

Assign in the constructor when the value is known there; use a definite assignment assertion only when initialization is guaranteed elsewhere.

Likely contributors, in order of frequency:

  • The field is declared without a default and not assigned in the constructor
  • The value is initialized in a separate lifecycle method the compiler cannot see
  • A DI framework assigns the field, so TypeScript cannot prove assignment

Root Cause

strictPropertyInitialization requires every declared property to be assigned before the constructor returns. Fields assigned only in a later method, or by external code, are flagged as not definitely assigned.

The Fix

Initialize at declaration, assign in the constructor, mark required injected fields with the definite assignment assertion ! and document why, or model the property as optional when it can be absent.

Watch out: The ! assertion disables the check entirely; a genuinely unset property then becomes undefined at runtime.

class User {
  name: string = 'anonymous';        // default initializer
  email!: string;                     // assigned by DI / framework
  age?: number;                       // genuinely optional

  constructor(id: string) {
    this.id = id;
  }

  readonly id: string;
}

Verify and Prevent

Run tsc –noEmit and confirm TS2564 is gone; a test constructs the object and asserts the property is set.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.