Hur använder jag en klass som är definierad i en TypeScript-deklarationsfil?
Jag försöker skapa en typings-fil för denna enkla köimplementation.
I mitt TS-projekt har jag skapat en mapp som heter customTypings och pekat på den i typeRoots-egenskapen i min tsconfig.json-fil.
Så här ser min .d.ts-fil ut:
declare module 'queue-fifo' {
export default class Queue {
constructor();
isEmpty(): boolean;
size(): number;
clear(): void;
enqueue(data: any): void;
dequeue(): any;
peek(): any;
}
}
Jag importerar den som: import Queue från 'queue-fifo';
Och sedan försöker jag skapa en instans av Queue-klassen: const queue=new Queue();
Vid det här laget får jag inga typfel i VS Code, och jag får heller inga kompilationsfel. Däremot, när jag försöker köra min kod genom debuggern, får jag:
Exception has occurred: TypeError
TypeError: queue_fifo_1.default is not a constructor
at BinarySearchTree.bfs (/../binarySearchTree.ts:110:23)
at testBst (/../binarySearchTree.ts:139:10)
at Object.<anonymous> (/../binarySearchTree.ts:144:1)
at Module._compile (module.js:632:14)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)
at Function.Module.runMain (module.js:676:10)
at startup (bootstrap_node.js:187:16)
Om jag bryter vid den raden ser jag att Queue (det jag importerade) är odefinierad, men queue_fifo_1 är definierad, och jag kan skapa en instans av klassen med det namnet medan jag är i debugkonsolen.
Kan någon förklara vad jag gör fel i min deklaration/konsumtion av deklarationen som orsakar detta oönskade beteende?
Svar #1
Lösning
Modulen queue-fifo använder CommonJS-stil export=Queue, vilket inte är kompatibelt med ES6-importer, och ger dig ingen standardexport. Den korrekta typdefinitionen måste använda samma export =-stil syntax:
declare module "queue-fifo" {
class Queue {
isEmpty(): boolean;
size(): number;
// etc
}
export = Queue;
}
Vilket kan importeras med CommonJS-stil import:
import Queue = require("queue-fifo");
const queue = new Queue();
ES6 import
Om du undrar om det är möjligt att importera den här modulen med ES6-syntax, kan du förmodligen använda namespace-definitionsknepet:
class Queue { /* ... */ }
namespace Queue { /* empty */ }
export = Queue;
Importera det sedan med ES6 jokertecken:
import * as Queue from "queue-fifo";
const queue = new Queue();
Men detta kommer endast att fungera i icke-ES6-miljöer, till exempel gör bundlers som Webpack och Rollup detta möjligt idag, men framtida ES6-kompatibla modulsystem kommer inte att kunna göra detta. Se mer här: Vad betyder "... resolves to a non-module entity and cannot be imported using this construct"?
