Skip to content

TypeScript Declaration Files

One of TypeScript's core advantages is its ability to seamlessly work with existing JavaScript libraries and code. However, standard JavaScript files (.js) don't contain type information themselves. To help the TypeScript compiler understand the types, function signatures, and object shapes of these JavaScript libraries, we use declaration files.

Declaration files have a .d.ts extension and don't contain any implementation code (function bodies, variable initial values, etc.), only type definitions.

Why Do We Need Declaration Files?

When you use a popular JavaScript library (like jQuery, Lodash, React), you want to get type checking and intelligent auto-completion when calling its functions in TypeScript code. Declaration files are the bridge that provides this type information.

Without declaration files:

typescript
// Suppose we're using 'my-library' without a declaration file
import { doSomething } from 'my-library';

// TypeScript compiler will error because it doesn't know what 'my-library' is,
// nor does it know about the doSomething function's existence and parameter types.
// Error: Cannot find module 'my-library'.
doSomething(123);

With declaration files:

typescript
// my-library.d.ts (declaration file)
declare module 'my-library' {
    export function doSomething(value: number): string;
}
typescript
// app.ts (your code)
import { doSomething } from 'my-library';

doSomething(123); // OK
// doSomething("hello"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.

How to Get Declaration Files?

For most popular JavaScript libraries, you don't need to manually write declaration files. The community has already done this work for us.

1. Libraries with Built-in Declaration Files

Many modern libraries already include their own .d.ts declaration files when published. When you install these libraries through npm, the declaration files are automatically recognized by TypeScript.

2. DefinitelyTyped Project

For JavaScript libraries that don't include type declarations themselves, there's a massive community project called DefinitelyTyped that provides high-quality declaration files for thousands of libraries.

These declaration files are all published under the @types scope on npm. You just need to install the corresponding @types package.

For example, to install declaration files for the lodash library, simply run:

bash
npm install --save-dev @types/lodash

After installation, you can use lodash in your TypeScript project just like a native TypeScript library.

Writing Your Own Declaration Files

In some cases, you may need to write declaration files for your own JavaScript code or a third-party library that doesn't have type definitions.

The declare Keyword

The declare keyword is used to tell TypeScript that a variable, function, or module exists and has a specific type, but its actual implementation is elsewhere (usually in a .js file).

Declaring a global variable:

typescript
// global.d.ts
declare const MY_GLOBAL_VARIABLE: string;

Declaring a module:

typescript
// my-untyped-module.d.ts
declare module 'my-untyped-module' {
    export function someFunction(arg: string): boolean;
    export const someConstant: number;
}

Declaration File Structure

  • Global declarations: If your JavaScript code runs in the global scope (for example, included via a <script> tag), you can directly use declare var, declare function, etc. in the .d.ts file.
  • Modular declarations: If your JavaScript code is a module, you should use the declare module 'module-name' { ... } syntax.

Writing high-quality declaration files can be complex and requires a deep understanding of TypeScript's type system. However, for most developers, the main task is consuming (rather than creating) declaration files.

  • "noImplicitAny": true: This is a recommended option to enable. When it's true, if TypeScript cannot infer a variable's type and there's no corresponding declaration file, it will error rather than implicitly treating it as any type. This helps you discover places in your project that lack type definitions.
  • "typeRoots" and "types": These options let you control where the compiler looks for declaration files. Typically, you don't need to manually configure them.

Content is for learning and research only.