Ruan Mendes
Ruan Mendes

Reputation: 92274

How to make TypeScript infer the type of dynamic new() calls

I am dynamically creating subclasses and I would like the factory function to know the subclass's return type.

I can do it with a cast but I would like to know if there's a way to infer it without requiring a cast.

class Hello { 
  a = 1;
}

class Hello2 extends Hello{ 
  b = 2; 
}

class Hello3 extends Hello { 
  c = 3; 
}

function create<T extends typeof Hello>(ctor: T): InstanceType<T> {
  // If I don't cast this, it won't compile
  return new ctor() as InstanceType<T>;
}

// Fails as it should because it's not a constructor of the right type
const h1 = create(Number);
const h2 = create(Hello2); 
console.log(h2.b); // no error
const h3 = create(Hello3);
console.log(h3.c); // no error

Upvotes: 2

Views: 181

Answers (1)

ford04
ford04

Reputation: 74510

What, if you instead make the class instance generic (not the static side/constructor function)? That should work out for you, like here:

class Hello { 
  a = 1;
}

class Hello2 extends Hello{ 
  b = 2; 
}

class Hello3 extends Hello { 
  c = 3; 
}

function create<T extends Hello>(ctor: new() => T) {
  return new ctor()
}

const h1 = create(Number); // error
const h2 = create(Hello2); // h2: Hello2
console.log(h2.b); // no error
const h3 = create(Hello3); // h3: Hello3
console.log(h3.c); // no error

If needed, you could define additional arguments to be passed like create<T extends Hello>(ctor: new(...args: any[]) => T) or in a more specific manner.

Upvotes: 1

Related Questions