declare and .d.ts files

Describing the types of something that exists outside your TypeScript code: global variables, JavaScript libraries, and modules.

On this page

Example

#
TypeScript
// src/types/globals.d.ts
declare const APP_VERSION: string
declare function trackEvent(name: string, data?: Record<string, unknown>): void

// src/lesson.ts
trackEvent('lesson_completed', { lesson: 'flexbox', version: APP_VERSION })

trackEvent(42)
// Error: Argument of type 'number' is not assignable to parameter of type 'string'.

The bundler inserts the value of APP_VERSION during the build, and the trackEvent function is added by an analytics script included on the page. The compiler only knows about them because of the declarations.

Definition and usage

#

The declare keyword tells the compiler that something exists, even though it wasn’t defined in this spot: a variable injected by another script on the page, a function from a library written in JavaScript, or an entire module. The declaration only describes the type and disappears after compilation, it creates no code.

Files with the .d.ts extension contain only descriptions like that, with no implementation. The compiler generates them from your code with the declaration option, and library authors bundle them with their npm packages. For packages with no types of their own, there are @types/… packages from the DefinitelyTyped repository, for example @types/lodash.

In your own project, a .d.ts file comes in handy for describing global variables, extending built-in types with declare global, and importing files that aren’t code, for example declare module "*.svg". The file has to be covered by include in tsconfig.json, otherwise the compiler won’t see it.

Syntax

#
Syntax
declare const name: type
declare function name(param: type): type
declare module "package" { … }
declare global { … }

Kinds of declarations

#
  • declare const

    A global variable, for example one injected by a bundler or a script included on the page. Instead of const you can use let or var.
  • declare function

    A function available globally. You can give several signatures, just like with overloads.
  • declare class

    A class defined outside TypeScript, for example in an older library.
  • declare module

    The types of an entire module: an npm package ("legacy-charts") or a file pattern ("*.svg").
  • declare global

    Adds declarations to the global scope from inside a module, for example a new field on Window.

More examples

#
Types for a package with no types
TypeScript
// src/types/legacy-charts.d.ts
declare module 'legacy-charts' {
  interface ChartOptions {
    title: string
    values: number[]
    color?: string
  }

  export default function drawChart(element: HTMLElement, options: ChartOptions): void
}

// src/progress.ts
import drawChart from 'legacy-charts'

drawChart(document.body, { title: 'Progress' })
// Error: Argument of type '{ title: string; }' is not assignable to parameter of type 'ChartOptions'.
//   Property 'values' is missing in type '{ title: string; }' but required in type 'ChartOptions'.
A new field on the window object
TypeScript
// src/types/window.d.ts
export {}

declare global {
  interface Window {
    dataLayer: unknown[]
  }
}

// any file in the project
window.dataLayer.push({ event: 'signup' })

The export {} line turns the file into a module. Without it, the compiler reports “Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.”

Good practices

#
  • Before writing your own types for a package, check whether a @types/package-name package exists. The message “Could not find a declaration file for module” usually suggests it on its own.
  • The shorthand declare module "package"; with no body silences the error, but then everything from the module gets the type any. Treat it as a temporary fix.
  • declare doesn’t create anything. If the variable truly doesn’t exist in the running program, the compilation passes, and the program stops with an “is not defined” error.

Related entries

#

Spotted a mistake or missing an example? Write to us.