Antoine Lehurt

How to create declaration files for JavaScript dependencies in TypeScript

In this article, I used TypeScript v3.

In TypeScript, declaration files (.d.ts) are used to describe the shape of a JavaScript module. By default, TypeScript can’t infer types, so you need to define these files to help the type checker, but also to get better autocompletion in your code editor. When importing a dependency into a TypeScript code base, you might get this error.

error TS7016: Could not find a declaration file for module 'my-dependency'.

The first solution that could be used in case you are starting to use TypeScript in an existing JavaScript project is to set noImplicitAny in your tsconfig.json.

{
  "compilerOptions": {
    "noImplicitAny": false
  }
}

TypeScript will assume that non annotated properties have the type any. This is helpful to update the codebase gradually, but you lose TypeScript safety.

The second option is to check if your dependency has a declaration file already created in the DefinitelyTyped repository. You can search it on TypeSearch website. If you are lucky, you will find it, and you need to install it as a dependency.

npm install --save-dev @types/my-dependency

But sometimes you won’t find it, and that leads us to the third solution, writing your own declaration file.

Writing you own declaration file

You can find different declaration file templates in the official documentation, but let’s go through an example.

You have imported koa-static-server module, and it doesn’t have a declaration file in DefinitelyTyped. So, as you’ve seen earlier in the article, you need to write one locally.

First, you need to update typeRoots in tsconfig.json to let the compiler know where to find the local declaration files.

{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types/", "./src/@types"]
  }
}

Here, you can write the local declaration file in src/@types.

And finally, you can create the declaration file for koa-static-server

mkdir src/@types/koa-static-server/index.d.ts

In this example I haven’t put the entire type declaration for this module.

declare module 'koa-static-server' {
  import Koa from 'koa';

  interface Options {
    rootDir: string;
    rootPath: string;
    gzip: boolean;
  }

  export default function staticServer(options: Options): Koa.Middleware;
}

declare statement declares the module on a global level, so we don’t need to import it in our code. TypeScript does it automatically via the typeRoots flag. The code inside the module declaration is similar to a TypeScript module: you expose the functions with their types that are defined in the JavaScript module.

I recommend you to check the official documentation to have more examples, but keep in mind that some of them use an older TypeScript’s syntax such as export = staticServer instead of export default.