How to fix Constructor of class 'X' is not compatible with constructor signature of type 'Y' in TypeScript

TypeScriptINTERMEDIATEHIGHUpdated Dec 8, 2025ยท 92 views

This error occurs when a class's constructor signature doesn't match the constructor signature expected by a type or interface. TypeScript is strict about constructor compatibility when using classes with type-based constructor signatures.

Quick fix

Fixes TS2322

// If you see this error:
// Type 'MyClass' is not assignable to type 'ConstructorType'
// Constructor of class 'MyClass' is not compatible with
// constructor signature of type 'ConstructorType'

type ConstructorType = new (x: string, y: number) => any;

class MyClass {
  constructor(x: number) {
    // Parameter order/types don't match
  }
}

const ctor: ConstructorType = MyClass; // ERROR
  1. Understand the type being assigned
  2. Fix the class constructor parameters
  3. Handle optional/variadic parameters correctly
  4. Use the constructor type pattern for factories
typescript โ€” error
// If you see this error:
// Type 'MyClass' is not assignable to type 'ConstructorType'
// Constructor of class 'MyClass' is not compatible with
// constructor signature of type 'ConstructorType'
type ConstructorType = new (x: string, y: number) => any;
class MyClass {
constructor(x: number) {
// Parameter order/types don't match
}
}
const ctor: ConstructorType = MyClass; // ERROR
Constructor of class 'X' is not compatible with constructor signature of type 'Y'

What this error means

TypeScript has a unique constraint: classes have both an instance side and a static side. The instance side contains instance properties and methods, while the static side contains the constructor. When you define an interface with a constructor signature (using the `new` keyword) and try to use a class to satisfy that interface, TypeScript checks whether the class constructor matches. Similarly, if you assign a class to a variable that expects a specific constructor signature, TypeScript enforces compatibility. The key issue is that when you `implements` an interface, TypeScript only checks the instance side of the class, not the constructor. This is why you can have a class that implements an interface but still fail the constructor signature check. This error typically appears when: - A class is assigned to a type that expects a different constructor signature - A class constructor has different parameter types, order, or optionality than expected - You're using the class as a factory function in code that expects a specific constructor shape

Typical symptoms

  • TypeScript compiler error when assigning a class to a variable with a constructor type
  • Error appears when passing a class as an argument to a function expecting a constructor type
  • Works fine with class instances but fails when referencing the class constructor itself
  • Removing specific parameters from the constructor causes the error to disappear
  • Adding optional parameters or changing parameter types changes the error
  • Using `implements` on an interface with constructor signatures fails compilation

Common causes

  1. Class constructor parameters don't match the expected type signature (most common)
  2. Parameter order is different between the class and the expected type
  3. Parameter types differ (e.g., string vs number)
  4. One constructor has optional parameters while the other doesn't
  5. Using class instantiation in a context that expects a constructor type reference
  6. Trying to implement an interface that includes a constructor signature
  7. Variance mismatch with constructor parameter types (contravariance rules apply)

How to fix "Constructor of class 'X' is not compatible with constructor signature of type 'Y'"

1Understand the type being assigned

First, identify what type signature the class needs to match. Look at the error message carefully:

typescript
// If you see this error:
// Type 'MyClass' is not assignable to type 'ConstructorType'
// Constructor of class 'MyClass' is not compatible with
// constructor signature of type 'ConstructorType'

type ConstructorType = new (x: string, y: number) => any;

class MyClass {
  constructor(x: number) {
    // Parameter order/types don't match
  }
}

const ctor: ConstructorType = MyClass; // ERROR

The error tells you exactly what the expected constructor signature is.

2Fix the class constructor parameters

Modify the class constructor to match the expected parameter types and order:

typescript
type ConstructorType = new (x: string, y: number) => any;

class MyClass {
  constructor(x: string, y: number) {
    // Now matches the expected signature
  }
}

const ctor: ConstructorType = MyClass; // OK

Make sure:
- Parameter names match (TypeScript checks this)
- Parameter types match exactly
- Parameter order matches
- Optional parameters are in the right places

3Handle optional/variadic parameters correctly

If the expected constructor has optional parameters, match that in your class:

typescript
// Expected: optional parameter
type ConstructorType = new (x?: string) => any;

class MyClass {
  constructor(x?: string) {
    // Correctly matches optional parameter
  }
}

const ctor: ConstructorType = MyClass; // OK

// For rest parameters:
type VarConstructor = new (...args: any[]) => any;

class VarClass {
  constructor(...args: any[]) {
    // Correctly matches variadic parameters
  }
}

const varCtor: VarConstructor = VarClass; // OK
4Use the constructor type pattern for factories

If you're trying to create a factory pattern, split the interface into constructor and instance types:

typescript
// WRONG: Trying to implement constructor signature directly
interface ClockConstructor {
  new (hour: number, minute: number): Clock;
}

// Can't do this - class implements only the instance side
class Clock implements ClockConstructor {
  constructor(h: number, m: number) {}
  tick() {}
}

// RIGHT: Create separate types
interface Clock {
  tick(): void;
  hour: number;
  minute: number;
}

interface ClockConstructor {
  new (hour: number, minute: number): Clock;
}

class Clock implements Clock {
  hour: number;
  minute: number;

  constructor(h: number, m: number) {
    this.hour = h;
    this.minute = m;
  }

  tick() {
    this.minute++;
  }
}

// Now you can use Clock as a constructor
const ctor: ClockConstructor = Clock; // OK
5Check parameter type variance

Remember that constructor parameters are contravariant. A constructor accepting a broader type can't be used where a stricter type is expected:

typescript
type ConstructorType = new (x: string | number) => any;

class MyClass {
  // WRONG: Requires a string, but constructor type accepts string | number
  constructor(x: string) {
    // Parameter type is too strict
  }
}

const ctor: ConstructorType = MyClass; // ERROR

// CORRECT: Accept the same or broader type
class MyClass {
  constructor(x: string | number | boolean) {
    // Parameter type is equal to or broader
  }
}

const ctor: ConstructorType = MyClass; // OK
6Verify with instanceof or type guard

After fixing the constructor signature, verify your class works as expected:

typescript
type ConstructorType = new (x: string) => { getValue(): string };

class MyClass {
  private value: string;

  constructor(x: string) {
    this.value = x;
  }

  getValue() {
    return this.value;
  }
}

// Use the constructor
const ctor: ConstructorType = MyClass;
const instance = new ctor("hello");
console.log(instance.getValue()); // "hello"

// Verify the instance
if (instance instanceof MyClass) {
  console.log("Instance created successfully");
}

Advanced notes

### Mixin Patterns and Constructor Constraints

When using mixin patterns, the type parameter must be constrained to a mixin constructor type:

typescript
type Constructor = new (...args: any[]) => {};

function Timestamped<T extends Constructor>(Base: T) {
  return class extends Base {
    timestamp = Date.now();
  };
}

// Works: constructor accepts any arguments
class User {
  constructor(name: string) {}
}

const TimestampedUser = Timestamped(User); // OK

### Constructor Return Type Mismatch

The error TS2203 (Construct signature return types differ) occurs when constructors return different types:

typescript
type ConstructorA = new () => { x: number };
type ConstructorB = new () => { x: string };

// Can't assign ConstructorB to ConstructorA
// because return types don't match

### Static vs Instance Side

Remember that implements checks only the instance side:

typescript
interface MyInterface {
  instanceMethod(): void;
}

interface MyStaticInterface {
  new (): MyInterface;
  staticMethod(): void;
}

class MyClass implements MyInterface {
  instanceMethod() {}
  static staticMethod() {}
}

// This checks only instance side (OK)
const instance: MyInterface = new MyClass();

// This checks constructor and static side (may fail)
const ctor: MyStaticInterface = MyClass as any;

Frequently asked questions

What does "TS2322" mean?
TypeScript has a unique constraint: classes have both an instance side and a static side. The instance side contains instance properties and methods, while the static side contains the constructor. When you define an interface with a constructor signature (using the new keyword) and try to use a class to satisfy that interface, TypeScript checks whether the class constructor matches.
How do I fix "TS2322"?
This error occurs when a class's constructor signature doesn't match the constructor signature expected by a type or interface. TypeScript is strict about constructor compatibility when using classes with type-based constructor signatures.
What causes "TS2322"?
Class constructor parameters don't match the expected type signature (most common) Parameter order is different between the class and the expected type Parameter types differ (e.g., string vs number)
Is the "TS2322" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading