Cómo escribir la declaración para una clase y un espacio de nombres con el mismo nombre en TypeScript
Estoy usando una biblioteca de Javascript de terceros en este formato:
var MyClass = function (name) {
this.name = name;
}
MyClass.prototype.greet = function () {
window.alert('Hello ' + this.name)
}
Quiero escribir una declaración de Typescript para esto. Tengo este tipo de cosa:
declare class MyClass {
constructor(name: string);
greet(): void;
}
Todo esto se está compilando bien y cuando solo quiero referirme a los tipos, funciona como se esperaba. Pero estoy teniendo problemas al intentar usar la implementación de la clase.
Usándolo de esta manera, se compila y se ejecuta, pero no obtengo verificación en tiempo de compilación
const MyClass = (require('./MyClass') as any).MyClass;
const a = new MyClass('Bob'); //a is any
Usándolo de esta manera obtengo un error de compilación
const MyClass = (require('./MyClass') as any).MyClass as MyClass;
const a = new MyClass('Bob'); //Cannot use 'new' with an expression whose type lacks a call or construct signature.
Usándolo de esta manera obtengo un error de compilación
import './MyClass';
const a = new MyClass('Bob');
//duplicate identifier in MyClass.d.ts
Respuesta #1
Entonces, el primer problema es que tu archivo de declaración es para el módulo MyClass y define la clase, pero no describe las exportaciones de ese módulo. El segundo problema es que luego necesitas la declaración de importación correspondiente en tu módulo principal. import './MyClass' es solo para importar efectos secundarios (ver la documentación de módulos de TypeScript).
Basado en el código que funciona, parece que el módulo MyClass exporta un objeto con una propiedad MyClass (establecida en la clase MyClass), así que eso es lo que he agregado a tu archivo de declaración.
El archivo de declaración MyClass.d.ts para el módulo js:
declare class MyClass {
constructor(name: string);
greet(): void;
}
export { MyClass }
Luego, en tu main.ts:
import { MyClass } from './MyClass';
let a = new MyClass('foo');
a.greet();
Respuesta #2
Intentaría algo así
declare class MyClass {
greet(): void;
}
declare type MyClassFactory = (x: string) => MyClass
const factory = (require('./MyClass') as any).MyClass as MyClassFactory;
const a = factory('Bob');
que es separar la clase y su función constructora
