gmanzoli
gmanzoli

Reputation: 77

TypeScript library types definition

I'm trying to write my own library definition for an open source project (https://github.com/opensourceBIM/BIMserver-JavaScript-API), but i'm stuck.

I've managed to clone the repo, and to write the types for the bimserverapipromise.js module, so now i have the bimserverapipromise.d.ts (gist) and i can write:

// index.ts
import BimServerApiPromise from "BimServerApiPromise";
let x = new BimServerApiPromise();

The troubles starts with the bimserverclient.js module, where the same approach doesn't work: i made a bimserverclient.d.ts with the definitions (gist), but the compiler seems unable to load the module.

// index.ts
import BimServerClient from "BimServerClient";  // VSCode error: module not found
let y = new BimServerClient();

The folder structure of the project is:

|- /index.ts
|- /tsconfig.json
|_ /BIMServerJavaScriptApi/bimserverclient.d.ts
|_ /BIMServerJavaScriptApi/bimserverclient.js
|_ /BIMServerJavaScriptApi/bimserverapipromise.d.ts
|_ /BIMServerJavaScriptApi/bimserverapipromise.js
|_ /BIMServerJavaScriptApi/** other files **

The tsconfig.json is the following:

{
    "compileOnSave": true,
    "compilerOptions": {
        "module": "commonjs",
        "allowJs": false,
        "sourceMap": true,
        "listFiles": true,
        "target": "es5",
        "lib": ["es2016", "dom"]
    },
    "include": [
        "./**/*.ts"
    ]
}

What am i missing? it's something due to the multiple import/export of the bimserverclient.js module, or perhaps it's because the type definition covers only one part of the JS module export?

Upvotes: 0

Views: 824

Answers (1)

Matt McCutchen
Matt McCutchen

Reputation: 30939

The reason that BimServerClient behaves differently than BimServerApiPromise is that your declare module 'BimServerClient' statement appears in a file with a top-level import, so it is being treated as a module augmentation instead of a module declaration. You could fix that by moving the import BimServerApiPromise from 'BimServerApiPromise'; inside the declare module 'BimServerClient' { ... } block.

However, a bigger question is whether it is correct to declare modules named BimServerClient and BimServerApiPromise in the first place. These names won't work to import the JavaScript modules at runtime unless the calling project sets up some special module loader or bundler configuration. I'd suggest removing the declare module statement and just putting the contained declarations at the top level of the file. Then any import that resolves to one of the JavaScript files according to normal Node.js module resolution rules will automatically pick up the corresponding .d.ts file for TypeScript. For your file layout, the correct relative import path to use from index.ts would be ./BIMServerJavaScriptApi/bimserverclient and/or ./BIMServerJavaScriptApi/bimserverclient.js (depending on your module loader or bundler), whereas if you were to install BIMServerJavaScriptApi as an npm package at node_modules/bimserverapi, you would use the non-relative import path bimserverapi/bimserverclient and/or bimserverapi/bimserverclient.js or simply bimserverapi (relying on the main field of package.json). If you are having trouble with your imports, please update the question and I will be happy to help further.

Upvotes: 2

Related Questions