This TypeScript error occurs when a constructor parameter property has a default value whose type does not match the declared type of the property. It's a type safety check ensuring that default values are compatible with the property type. Aligning the default value type with the property declaration resolves this issue.
This error indicates a type mismatch between a constructor parameter property's declared type and its default value. When using TypeScript's parameter property shorthand (prefixing constructor parameters with public, private, protected, or readonly), the default value you assign must be compatible with the property's explicit type annotation. TypeScript's type checker ensures that if you declare a property as a specific type, its default value must be assignable to that type. This prevents runtime errors where a property might contain an unexpected value type. The error commonly occurs when declaring a property as one type (like string) but providing a default value of another incompatible type (like number), or when the default value could be null/undefined but the property type doesn't allow those values.
Read the error message to locate which constructor parameter property has the type mismatch. The error will indicate the declared type and the actual default value type.
// ERROR: Default type 'number' is not assignable to declared type 'string'
class User {
constructor(
public name: string = 123 // WRONG - default is number, not string
) {}
}Change the default value to match the declared property type. Make sure the literal value or expression you use for the default is assignable to the property type.
// CORRECT - default value matches declared type
class User {
constructor(
public name: string = "Guest" // OK - both are string
) {}
}
// CORRECT - number default for number type
class Counter {
constructor(
public count: number = 0 // OK - both are number
) {}
}If you want to allow null or undefined as a default value, explicitly include these in the type annotation using a union type.
// ERROR - null not assignable to string
class User {
constructor(
public email: string = null // WRONG
) {}
}
// CORRECT - include null in type
class User {
constructor(
public email: string | null = null // OK - null is now valid
) {}
}
// OR use undefined for optional
class User {
constructor(
public email?: string // OK - implicitly string | undefined, no default needed
) {}
}When using literal types (specific strings, numbers, or union of literals), ensure the default value is one of the allowed literal values.
type Status = "active" | "inactive" | "pending";
// ERROR - "unknown" is not in the Status union
class Account {
constructor(
public status: Status = "unknown" // WRONG
) {}
}
// CORRECT - use a valid literal from the union
class Account {
constructor(
public status: Status = "pending" // OK - "pending" is in Status
) {}
}For complex types like objects or arrays, ensure the default value structure matches the declared type exactly, including all required properties.
interface Config {
host: string;
port: number;
}
// ERROR - missing required property 'port'
class Server {
constructor(
public config: Config = { host: "localhost" } // WRONG
) {}
}
// CORRECT - include all required properties
class Server {
constructor(
public config: Config = { host: "localhost", port: 3000 } // OK
) {}
}If the explicit type annotation is causing issues and you want the property type to be inferred from the default value, remove the type annotation and let TypeScript infer it.
// With explicit type - must match
class Settings {
constructor(
public timeout: number = 5000 // type must be number
) {}
}
// Let TypeScript infer - type becomes number from default
class Settings {
constructor(
public timeout = 5000 // inferred as number
) {}
}If you have a complex default value that you're certain matches the type but TypeScript cannot verify, use a type assertion with as. Use this sparingly.
interface ComplexConfig {
[key: string]: string | number;
}
// If TypeScript has trouble inferring
class App {
constructor(
public config: ComplexConfig = { timeout: 1000 } as ComplexConfig
) {}
}Check your TypeScript configuration. With strict mode or strictNullChecks enabled, null and undefined are not assignable to most types unless explicitly allowed.
{
"compilerOptions": {
"strict": true, // Enables all strict checks
"strictNullChecks": true // null/undefined must be explicit in types
}
}With strict mode, adjust your types accordingly:
// With strict mode OFF - this might work
class User {
constructor(public name: string = null) {} // null might be allowed
}
// With strict mode ON - must be explicit
class User {
constructor(public name: string | null = null) {} // OK - null is allowed
}Constructor parameter properties are a TypeScript shorthand feature that combines parameter declaration and class property initialization in one step. When you use visibility modifiers (public, private, protected) or readonly on constructor parameters, TypeScript automatically creates a class property and assigns the parameter value to it. This feature is purely syntactic sugar that makes class definitions more concise. The type checking rules for parameter properties are the same as for regular class properties: the assigned value (including default values) must be assignable to the declared type. One subtle consideration is the interaction between optional parameters (using ?) and default values. A parameter like public name?: string is equivalent to public name: string | undefined, which means undefined is a valid value. However, providing an explicit default value (like public name: string = "default") makes the parameter optional at call time but ensures the property is never undefined at runtime. When working with complex types, particularly discriminated unions or conditional types, TypeScript may struggle to verify that a default value matches the declared type; in such cases, consider using factory methods or separate initialization logic instead of constructor defaults. The strictPropertyInitialization flag (part of strict mode) requires that all class properties be initialized either at declaration or in the constructor, which affects how you structure your parameter properties and defaults.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript