Skip to content

TS2564: Property 'X' has no initializer and is not definitely assigned in the constructor

This error occurs when a class property is not initialized and TypeScript cannot guarantee it will be assigned before use.

With strictPropertyInitialization enabled, all properties must be initialized in the constructor or at declaration.


class User {
name: string;
email: string;
// ❌ Property 'name' has no initializer and is not definitely assigned in the constructor
// ❌ Property 'email' has no initializer and is not definitely assigned in the constructor
}
const user = new User();
console.log(user.name.toUpperCase()); // Runtime error: cannot read property of undefined

TypeScript considers these possibilities:

  • Properties are undefined until assigned
  • Accessing undefined.toUpperCase() will crash at runtime

Without initialization, TypeScript cannot guarantee type safety.


Section titled “Option 1: Initialize in constructor (recommended)”
class User {
name: string;
email: string;
constructor(name: string, email: string) {
this.name = name;
this.email = email;
}
}
const user = new User("Alice", "alice@example.com"); // ✅

When to use:

  • ✅ Safest and most common approach
  • ✅ Values are provided at construction time

class User {
name: string = "Guest";
email: string = "guest@example.com";
}
const user = new User(); // ✅

When to use:

  • ✅ When you have sensible default values
  • ✅ Simple and clear

class User {
name?: string;
email?: string;
}
const user = new User();
console.log(user.name?.toUpperCase()); // ✅ Safe with optional chaining

When to use:

  • ✅ When properties might legitimately be undefined
  • ✅ Forces consumers to handle undefined case

Option 4: Definite assignment assertion (use sparingly)

Section titled “Option 4: Definite assignment assertion (use sparingly)”
class User {
name!: string; // ! tells TypeScript "trust me, this will be assigned"
email!: string;
constructor() {
this.initialize();
}
initialize() {
this.name = "Alice";
this.email = "alice@example.com";
}
}

When to use:

  • ⚠️ Only when you’re certain the property will be assigned before use
  • ⚠️ Common with dependency injection or lifecycle methods
  • ⚠️ Can cause runtime errors if you’re wrong

class UserProfile extends React.Component {
private api: ApiClient;
// ❌ Property 'api' has no initializer
// ✅ Fix: Initialize in constructor
constructor(props) {
super(props);
this.api = new ApiClient();
}
}
class UserService {
private database!: Database; // Using ! because it's injected
setDatabase(db: Database) {
this.database = db;
}
}
class DataLoader {
data!: string[];
async load() {
this.data = await fetchData();
}
}
// Usage:
const loader = new DataLoader();
await loader.load(); // Must call before accessing data

  • Always initialize properties in the constructor or at declaration
  • Use optional properties (?) when undefined is valid
  • Avoid definite assignment assertion (!) unless necessary
  • This error prevents common “undefined is not an object” runtime errors