TypeScript - error: no se puede usar 'new' con una expresión cuyo tipo carece de una firma de llamada o de construcción
He identificado un problema al usar tipos de intersección en TypeScript...
Tengo tres alias de tipo:
Prototype<T>- expresa un objeto/clase que tiene una propiedadprototype.DefaultCtor<T>- expresa un objeto/clase con un constructor por defecto.ParameterizedCtor<T>expresa un objeto/clase con un constructor parametrizado.
He probado estas permutaciones de intersección:
Prototype<T> & DefaultCtor<T>- funciona bien.Prototype<T> & ParameterizedCtor<T>- genera un error de compilador.
Ejemplo
type Prototype<T> = {
prototype: T;
}
type DefaultCtor<T> = {
new(): T;
}
type ParameterizedCtor<T> = {
new(...args: any[]): T
}
function makeDefault<T>(ctor: Prototype<T> & DefaultCtor<T>): T {
return new ctor();
}
function makeWithArgs<T>(ctor: Prototype<T> & ParameterizedCtor<T>, ...args: any[]): T {
return new ctor(...args);
// ERROR: Cannot use 'new' with an expression whose type lacks a call or construct signature.
}
Pruébalo en el Área de Juegos
Error El error ocurre con la intersección Prototype<T> & ParameterizedCtor<T>:
No se puede usar 'new' con una expresión cuyo tipo carece de una firma de llamada o de construcción.
¿Por qué el compilador de TypeScript reconoce el tipo de intersección Prototype<T> & DefaultCtor<T> como teniendo un constructor, pero no el tipo de intersección Prototype<T> & ParameterizedCtor<T>?
Respuesta #1
Esto parece ser un error conocido, registrado en Microsoft/TypeScript#17388, reportado en julio de 2017. Está previsto que se solucione en TypeScript v2.9, pero la historia del problema parece indicar que la versión de la corrección se ha pospuesto algunas veces. Ve allí y 👍 si te apetece, supongo. Espero que eso ayude. Buena suerte.
Respuesta #2
Solución alternativa
En algunos casos extremos, usar una conversión proporcionará una solución provisional mientras el equipo de TypeScript desarrolla una solución.
Ejemplo
function make<T>(ctor: Prototype<T> & ParameterizedCtor<T>, ...args: any[]): T {
console.log(ctor.prototype);
return new (ctor as ParameterizedCtor<T>)(...args);
}
