Tengo algunos archivos de TypeScript:
MyClass.ts
class MyClass {
constructor() {
}
}
export = MyClass;
MyFunc.ts
function fn() { return 0; }
export = fn;
MyConsumer.ts
import * as MC from './MyClass';
import * as fn from './MyFunc';
fn();
Esto me da errores al intentar usar new
El módulo "MyClass" se resuelve como una entidad que no es un módulo y no se puede importar con esta construcción.
y al intentar llamar fn()
No se puede invocar una expresión cuyo tipo carece de una firma de llamada.
¿Lo que da?
typescript
ecmascript-6
es6-modules
Ryan Cavanaugh
fuente
fuente
javascript
como etiqueta principal y salirecmascript-6
, porque la etiqueta principal aquí estypescript
. La pregunta asume erróneamente queexport =
(una función de TS) se puede emparejar conimport ... from
, mientras que debería emparejarse conimport =
. Es básicamente la importación / exportación del módulo ES6 frente a CJS / AMD.Respuestas:
Por que no funciona
Esta es la
import
sintaxis de estilo ES6 / ES2015 . El significado exacto de esto es "Tomar el objeto del espacio de nombres del módulo cargado./MyClass
y usarlo localmente comoMC
". En particular, el " objeto de espacio de nombres de módulo " consta solo de un objeto simple con propiedades. Un objeto de módulo ES6 no se puede invocar como función o connew
.Para decirlo de nuevo: un objeto de espacio de nombres de módulo ES6 no se puede invocar como una función o con
new
.Lo que
import
usa* as X
de un módulo está definido para que solo tenga propiedades. En CommonJS rebajado, esto podría no respetarse por completo, pero TypeScript le dice cuál es el comportamiento definido por el estándar.¿Qué funciona?
Necesitará usar la sintaxis de importación estilo CommonJS para usar este módulo:
Si controlas ambos módulos, puedes usar
export default
en su lugar:MyClass.ts
MyConsumer.ts
Estoy triste por esto; Las reglas son tontas.
Hubiera sido bueno usar la sintaxis de importación de ES6, pero ahora tengo que hacer esto
import MC = require('./MyClass');
. ¡Es tan 2013! ¡Cojo! Pero el dolor es una parte normal de la programación. Salte a la etapa cinco en el modelo Kübler-Ross: Aceptación.TypeScript aquí le dice que esto no funciona, porque no funciona. Hay hacks (agregar una
namespace
declaración aMyClass
es una forma popular de pretender que esto funciona), y podrían funcionar hoy en su paquete de módulos de bajada de nivel particular (por ejemplo, rollup), pero esto es ilusorio. Todavía no hay implementaciones del módulo ES6 en la naturaleza, pero eso no será cierto para siempre.Imagínese usted mismo en el futuro, tratando de ejecutar una implementación nativa del módulo ES6 y descubriendo que se ha preparado para una falla importante al intentar usar la sintaxis de ES6 para hacer algo que ES6 explícitamente no hace .
Quiero aprovechar mi cargador de módulos no estándar
Tal vez tenga un cargador de módulos que "provechosamente" crea
default
exportaciones cuando no existen. Quiero decir, la gente crea estándares por una razón, pero ignorarlos a veces es divertido y podemos pensar que es algo genial.Cambie MyConsumer.ts por:
Y especifique la
allowSyntheticDefaultImports
línea de comandos utsconfig.json
opción.Tenga en cuenta que
allowSyntheticDefaultImports
no cambia el comportamiento en tiempo de ejecución de su código en absoluto. Es solo una bandera que le dice a TypeScript que su cargador de módulos creadefault
exportaciones cuando no existen. No hará que su código funcione mágicamente en nodejs cuando antes no lo hacía.fuente
export = MyClass
? ¿Mi única opción es configurar mi módulocommonjs
y continuar haciendo del mundo un lugar peor al no usar ES moderno?--esModuleInterop
, dice "Recomendamos encarecidamente aplicarlo a proyectos nuevos y existentes". En mi opinión, esta respuesta (y la entrada / política de preguntas frecuentes enDefinitelyTyped
esos enlaces aquí) deberían modificarse para reflejar la nueva postura.TypeScript 2.7 introduce soporte mediante la emisión de nuevos métodos de ayuda: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form- commonjs-modules-con --- esmoduleinterop
Entonces en tsconfig.json agregue estas dos configuraciones:
Y ahora puedes usar:
fuente
esModuleInterop
, uséresolveJsonModule
junto con su otra sugerencia de usoallowSyntheticDefaultImports
y funcionó para mí.Agregando mis 2 centavos aquí en caso de que alguien más tenga este problema.
En mi forma de solucionar el problema sin modificar
tsconfig.json
(lo que puede ser problemático en algunos proyectos), he optado por deshabilitar simplemente la regla para la línea.import MC = require('./MyClass'); // tslint:disable-line
fuente
Recibí este error al intentar incluir un paquete antirrebote npm en mi proyecto.
Cuando probé la solución aceptada anterior, obtuve una excepción:
Esto terminó funcionando:
fuente