I'm attempting to create a typings file for this simple queue implementation.
In my TS project, I've created a folder called customTypings and pointed to it in the typeRoots property of my tsconfig.json file.
Here's what my .d.ts file looks like:
declare module 'queue-fifo' {
    export default class Queue {
        constructor();
        isEmpty(): boolean;
        size(): number;
        clear(): void;
        enqueue(data: any): void;
        dequeue(): any;
        peek(): any;
    }
}
I import is as: import Queue from 'queue-fifo';
And then I try to create an instance of the Queue class: const queue = new Queue();
At this point, I get no type errors in VS Code, nor do I get any compilation errors. However, when I try to run my code through the debugger, I get:
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)
If I break at that line, I see the Queue (what I imported) is undefined, but queue_fifo_1 is defined, and I can create an instance of the class using that name while in the debug console.
Can someone explain what I'm doing wrong in my declaration/consumption of the declaration that is causing this undesired behavior?
The queue-fifo module uses CommonJS-style export = Queue, which is not compatible with ES6 imports, and gives you no default export. The correct type definition will need to use the same export = style syntax:
declare module "queue-fifo" {
    class Queue {
        isEmpty(): boolean;
        size(): number;
        // etc
    }
    export = Queue;
}
Which can be imported using CommonJS-style import:
import Queue = require("queue-fifo");
const queue = new Queue();
If you're wondering if it's possible to import this module using ES6 syntax, you can probably use the namespace definition hack:
class Queue { /* ... */ }
namespace Queue { /* empty */ }
export = Queue;
Then import it using ES6 wildcard:
import * as Queue from "queue-fifo";
const queue = new Queue();
But this will only work in non-ES6 environments, for example bundlers like Webpack and Rollup make this work today, but future ES6 compliant module systems will not be able to make this work. See more here: What does "... resolves to a non-module entity and cannot be imported using this construct" mean?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With