expresión ‘nueva’, cuyo destino carece de una firma de construcción en TypeScript

5 minutos de lectura

avatar de usuario
fulvio

Tenemos lo siguiente TestComponent.ts Clase de mecanografiado:

01: import TestVectorLayer from './TestVectorLayer'
02: 
03: export class TestComponent implements OnInit {
04:   private foo: any;
05: 
06:   constructor() { }
07: 
08:   const layer = new TestVectorLayer("foo");
09: }

Y lo siguiente TestVectorLayer.ts función:

Tenga en cuenta que OpenLayer’s 3 está utilizando la biblioteca de cierre de Google, por eso TestVectorLayer no es una clase de TypeScript.

01: declare let ol: any;
02:
03: const TestVectorLayer = function (layerName: string) {
04:   ...
05:   console.log(layerName);
06:
07:   ol.layer.Image.call(this, opts);
08: }
09:
10: ol.inherits(TestVectorLayer as any, ol.layer.Image as any);
11:
12: export default TestVectorLayer; 

Estamos recibiendo el siguiente error:

Error on Line 08 in TestComponent.ts class:

[ts] La expresión ‘nueva’, cuyo objetivo carece de una firma de construcción, implícitamente tiene un tipo ‘cualquiera’. importar TestVectorLayer

los package.json versiones de TypeScript:

devDependencias:

"typescript": "~2.2.1"

  • Y si quieres new por que no puedo TestVectorLayer ser una clase?

    – Saravana

    26 de abril de 2017 a las 1:57

  • @Saravana esto no debería importar, al final del día, la clase es solo azúcar sintáctica.

    – WilomGfx

    26 de abril de 2017 a las 1:59


  • @AluanHaddad He actualizado la pregunta. TestVectorLayer está usando OpenLayer 3, que usa Google Closure Library.

    – fulvio

    26 de abril de 2017 a las 2:00


  • @fuzz por lo que está utilizando --allowJs? Todavía estoy un poco confundido porque si es una biblioteca de terceros, ¿por qué la consume desde una ruta relativa en lugar de su paquete con su paquete.json y archivos de licencia?

    – Aluan Haddad

    26 de abril de 2017 a las 2:05


  • @Saravana Cierto, no estaría de más hacer una clase. Solo por los beneficios de escribir.

    – WilomGfx

    26 de abril de 2017 a las 2:06

La respuesta de David es excelente, pero si solo le importa compilarlo rápidamente (por ejemplo, porque está migrando de JS a TS), simplemente puede poner any ahí para callarse el compilador quejándose.

archivo TS:

const TestConstructorFunction = function (this: any, a: any, b: any) {
    this.a = a;
    this.b = b;
};

let test1 = new (TestConstructorFunction as any)(1, 2);

compila a este archivo JS:

var TestConstructor = function (a, b) {
    this.a = a;
    this.b = b;
};
var test1 = new TestConstructor(1, 2);

Solo presta atención para no cometer este error:

archivo TS:

// wrong!
let test2 = new (TestConstructorFunction(1, 2) as any);

resultado JS:

// wrong!
var test2 = new (TestConstructor(1, 2));

y esto es equivocado. Obtendrás TypeError: TestConstructor(...) is not a constructor error en tiempo de ejecución.

  • Estoy migrando desde JS muy antiguo y esa sería la respuesta correcta en mi caso.

    usuario3025289

    2 de junio de 2020 a las 14:43

  • muchas gracias, funciona! const s1 = new (Student as any)('elite', 23);

    – xgqfrms

    3 de junio de 2020 a las 17:47


  • salvó mi día! necesito hacer que funcione para una clase que no escribí

    – Jacobo

    16 de marzo a las 4:44

  • Entonces, esta respuesta de nicho obtuvo más Me gusta que la adecuada. Esto es un poco alarmante ya que los recién llegados podrían pensar que es un enfoque normal. Es un truco, que es un poco mejor que @ts-ignore.

    – Onkeltem

    2 abr a las 13:02


  • @Onkeltem Sí, también me sorprendió que obtuviera más Me gusta. Bueno, la gente quiere arreglar el error del compilador y seguir adelante. No puedo culparlos. Supongo que es mejor que no usar Typescript en absoluto 😉 La respuesta aceptada es claramente mejor porque proporciona una definición de tipo adecuada para la función, por lo que se verifica el tipo en absoluto new FunCtr(...) llamadas Pero si solo tienes que arreglar un lugar donde se llame, entonces creo que no es gran cosa. OMI usando as any debe considerarse una mala práctica en general, pero a veces solo desea cerrar el compilador y seguir adelante …

    – Mariusz Pawelsky

    3 abr a las 18:03


avatar de usuario
David Sherret

He aquí una simplificación de la pregunta:

const TestVectorLayer = function(layerName: string) {
};

const layer = new TestVectorLayer("");

El error está ocurriendo porque TestVectorLayer no tiene una nueva firma, por lo que layer se escribe implícitamente como any. que falla con --noImplicitAny.

Puede solucionar esto cambiando a una clase, pero en su caso esto parece un poco más complicado porque la herencia la realiza el marco subyacente. Por eso, tendrás que hacer algo un poco más complicado y no es lo ideal:

interface TestVectorLayer {
  // members of your "class" go here
}

const TestVectorLayer = function (this: TestVectorLayer, layerName: string) {
  // ...
  console.log(layerName);
  ol.layer.Image.call(this, opts);
} as any as { new (layerName: string): TestVectorLayer; };

ol.inherits(TestVectorLayer, ol.layer.Image);

export default TestVectorLayer; 

Luego en el archivo con TestComponent:

const layer = new TestVectorLayer(layerName); // no more compile error

  • Su solución más complicada pero no ideal funciona. 🙂 Gracias por proporcionar una solución temporal. Intentaremos trabajar para cambiar a una clase. Originalmente cambiamos a una clase y encontramos un montón de problemas con la herencia, por eso optamos por el enfoque híbrido de las anotaciones JS y TS.

    – fulvio

    26 de abril de 2017 a las 3:22


  • @fuzz no hay problema! Puede haber una mejor manera… simplemente no puedo pensar en una en este momento.

    – David Sherret

    26 de abril de 2017 a las 3:32

  • @DavidSherret, ¿puede compartir dónde puedo obtener más información/documentos sobre as any as

    – Sohel Ahmed Mesaniya

    16 de mayo de 2019 a las 10:08

  • @SohelAhmedM leyó sobre aserciones de tipo aquí. as any es una aserción tipo a la any escribe. Haciendo value as any as T son aserciones de dos tipos y es una forma de afirmar el tipo de value como T cuando el tipo de value no se puede afirmar como T (ej. cuando value as T causaría un error de compilación, pero desea afirmarlo de todos modos). Esencialmente, es una forma de eludir el verificador de tipos.

    – David Sherret

    17 de mayo de 2019 a las 0:33

  • Tengo que amar Typescript. ¿Cuántas horas se pierden tratando de resolver estas cosas?

    – png

    18 de noviembre de 2020 a las 20:17

En mi caso, tienes que definirlo como any y tiene new firma, por ejemplo.

const dummyCtx = function(txt: string) {
  this.foo = txt
} as any as { new (txt: string): any }

// just use it as usual
const dctx = new dummyCtx('bar')

  • typescriptlang.org/docs/handbook/2/… Estaba leyendo los documentos mecanografiados y encontré el problema como en la pregunta anterior. Esto realmente resolvió el problema para mí.

    – Melvin Tehubijuluw

    20 dic 2021 a las 14:30


Le daría a su TestVectorLayer una interfaz

class TestVectorLayer implements TestVectorLayer {
    
}

interface TestVectorLayer {
    new (layerName: string): TestVectorLayer;
} 

¿Ha sido útil esta solución?