TypeScript Declaration Files
Author ambient declaration files, bundle package typings, augment global interfaces, and publish typed libraries for the community.
TL;DR
- Author
.d.tsfiles to describe types for external JavaScript modules. - Define ambient global variables using the root
declarekeyword modifier. - Specify package types mapping inside
package.jsonusing thetypesfield.
Ambient Declarations
Ambient variable declarationDeclare global variables defined at runtime.
declare const __API_VERSION__: string;
declare const __DEBUG__: boolean;Ambient function signatureType JavaScript functions without bodies.
declare function notifyUser(
message: string,
timeoutMs?: number
): void;Ambient class declarationDefine class methods and property signatures.
declare class ClientEngine {
constructor(apiKey: string);
connect(): Promise<boolean>;
}Global scope augmentationExtend global window or node namespaces.
declare global {
interface Window {
appConfig?: { env: string };
}
}Module Declarations
External module stubSupply types for untyped third-party packages.
declare module "legacy-logger" {
export function log(msg: string): void;
export const level: number;
}Module augmentationAdd custom properties to library interfaces.
import "express";
declare module "express" {
interface Request {
userId?: string;
}
}Wildcard asset declarationPermit importing SVG and image assets.
declare module "*.svg" {
const content: string;
export default content;
}CSS module declarationType CSS module classname dictionaries.
declare module "*.module.css" {
const classes: Record<string, string>;
export default classes;
}Package and NPM Typings
Basic package types fieldDirect compiler to main declaration file.
{
"name": "my-lib",
"main": "./dist/index.js",
"types": "./dist/index.d.ts"
}Exports map conditional typesMap types for ESM and CJS consumers.
{
"exports": {
".": {
"import": "./dist/esm/index.js",
"types": "./dist/index.d.ts"
}
}
}Compiler declaration emitInstruct tsc to emit d.ts and source maps.
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"outDir": "./dist"
}
}DefinitelyTyped and Testing
DefinitelyTyped file layoutStandard structure for Community @types packages.
// types/awesome-lib/
// index.d.ts
// package.json
// tsconfig.json
// awesome-lib-tests.tsConsumer type testAssert expected types in test suites.
import * as lib from "awesome-lib";
// Type checking assertions:
const res: string = lib.format("test");Avoid any in declarationsUse generic parameters rather than any.
// Prefer generics over any:
declare function parseData<T>(
raw: string
): T;Export equals for CommonJSModel legacy CommonJS single export modules.
declare function legacyRunner(): void;
export = legacyRunner;Tips
- Generate
.d.tsfiles automatically during build pipelines by settingdeclarationanddeclarationMapto true in compiler options. - Prefer
unknownand generic constraints in ambient function definitions instead of resorting to loose un-typedanyannotations.
Warnings
- Never import runtime JavaScript logic inside ambient
.d.tsfiles, as ambient declarations must contain purely erased type signatures. - Inaccurate ambient declarations worse than missing types; discrepancies between
declaresignatures and runtime behavior trigger subtle consumer errors.
In Practice
A complete .d.ts ambient declaration module defining an analytics SDK with method signatures, event types, and global interface augmentation.
- Define union event types and interface shapes.
- Declare the analytics client class and public method overloads.
- Augment the global Window interface to expose the client singleton.
- Export clean types without generating executable JavaScript overhead.
export type EventPayload =
| { name: "page_view"; path: string }
| { name: "click"; elementId: string };
export declare class AnalyticsClient {
constructor(config: { apiKey: string });
track(event: EventPayload): Promise<void>;
}
declare global {
interface Window {
__analytics?: AnalyticsClient;
}
}FAQ
A .ts file contains executable TypeScript code compiled into JavaScript. A .d.ts declaration file contains purely erased type contracts using declare statements without executable implementations. Declaration files guide editor autocompletion and compiler type checking for existing JavaScript modules.
Add the types or typings field to your package.json pointing to your emitted entry file, such as "types": "./dist/index.d.ts". For dual-module packages, configure type mappings inside the exports map under import.types and require.types.
Bundle .d.ts files directly in your package repository if you maintain the source code, as this keeps implementations and types synchronized upon each release. Submit to DefinitelyTyped under @types/pkg only when supplying external typings for third-party JavaScript libraries you do not own.
Module augmentation allows you to extend the typings of an existing library using declare module 'library-name'. You can merge new properties onto existing interfaces like Express Request or Extend Window globals without modifying third-party library source code.
Create a global declaration file (e.g. globals.d.ts) with wildcard module declarations such as declare module '*.svg' { const content: string; export default content; }. This informs the TypeScript compiler that importing static asset files returns string module assets.