Hur man får TypeScript att härleda typen för dynamiska new()-anrop


Jag skapar dynamiskt underklasser och jag skulle vilja att fabrikfunktionen känner till underklassens returtyp.

Jag kan göra det med en typomvandling, men jag skulle vilja veta om det finns ett sätt att sluta sig till det utan att kräva en typomvandling.

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

Svar #1

Vad händer om du istället gör klassinstansen generisk (inte den statiska sidan/konstruktionsfunktionen)? Det borde fungera för dig, som här:

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

Om det behövs kan du definiera ytterligare argument som ska skickas, till exempel create<T extends Hello>(ctor: new(...args: any[]) => T) eller på ett mer specifikt sätt.