Búsqueda de sitios web

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 propiedad prototype.
  • 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);
}