How should I define a global TypeScript variable in a definition file so that it can be imported?

2.2k views Asked by At

I have an external JS library with a global parameter:

function Thing() {  ...  }
...
var thing = new Thing();

There is a TypeScript definition file, so in thing.d.ts:

declare var thing: ThingStatic;
export default thing;

export interface ThingStatic {
    functionOnThing(): ThingFoo;
}

export interface ThingFoo {
    ... and so on

Then I import this into my own TS files with:

import thing from 'thing';
import {ThingFoo} from 'thing';
...
const x:ThingFoo = thing.functionOnThing();

The problem is that transpiles to:

const thing_1 = require("thing");
...
thing_1.default.functionOnThing();

Which throws an error. I've asked about that in another question, and the suggestion is to use:

import * as thing from 'thing';

That doesn't fix it - it gives me thing.default in TS but then that's undefined once transpiled to JS.

I think there's something wrong with thing.d.ts - there must be a way to define a typed global parameter that can be imported.

How should I write thing.d.ts so that it represents the JS correctly and doesn't transpile to include default or other properties not actually present?

1

There are 1 answers

3
artem On

If the only way to use that library is by accessing its globals (as opposed to importing it as node module or amd or umd module), then the easiest way to go is have a declaration file without any exports at top level. Just declaring a variable is enough. To use it, you have to include that declaration file when compiling your typescript code, either by adding it to files or include in tsconfig.json, or directly on command line. You also have to include the library with a <script> tag at runtime.

Example: thing.d.ts

declare var thing: ThingStatic;

declare interface ThingStatic {
    functionOnThing(): ThingFoo;
}

declare interface ThingFoo {
}

test-thing.ts

const x:ThingFoo = thing.functionOnThing();

can be compiled together

./node_modules/.bin/tsc test-thing.ts thing.d.ts

the result in test-thing.js:

var x = thing.functionOnThing();

See also this question about ambient declarations.

Note: there are module loaders out there that allow using global libraries as if they were modules, so it's possible to use import statement instead of <script> tag, but how to configure these module loaders to do that is another, more complicated question.