A declaration file gives the TypeScript compiler types for code without supplying its executable implementation. This is useful when a TypeScript application imports JavaScript: the compiler can check calls against the declared interface, while the JavaScript file still supplies the behavior. A declaration for a JavaScript file normally shares its name and uses the .d.ts extension—for example, src/formatters.d.ts describes src/formatters.js. section 15.3.2 section 15.5
Describe an existing JavaScript module
If formatters.js exports sizeFormatter(thing, count) and costFormatter(thing, cost), src/formatters.d.ts can contain: export declare function sizeFormatter(thing: string, count: number): void; export declare function costFormatter(thing: string, cost: number | string): void; The declare keyword says that the implementation exists elsewhere. If formatters.js later exports writeMessage, add its signature too before importing it from TypeScript. section 15.3.2
Keep the declaration accurate and complete for every feature the application uses. When a declaration file is present, the compiler relies on it rather than examining the corresponding JavaScript file; an exported JavaScript function omitted from the declaration appears unavailable. The compiler also trusts declared types even if the implementation does not match. Declaration files take precedence over JSDoc descriptions of the same code. section 15.3.2
For a third-party JavaScript package, choose the least work that supplies suitable declarations:
- Check whether the installed package includes declarations. For example, chalk@4.1.2 contains index.d.ts; its declarations let the compiler reject a nonexistent chalk.notAColor property. section 15.3.5
- Otherwise, look for a separate @types package. npm install --save-dev @types/debug installs publicly available declarations that the compiler finds under node_modules/@types. section 15.3.4
- Write a custom declaration when needed. For a CommonJS debug package, the example uses types/debug.d.cts and configures baseUrl and paths in tsconfig.json so imports resolve to it; the declaration extension must match the package’s module format. section 15.3.3
Custom and installed declarations can compete. If paths still directs resolution to a custom types folder, installing @types/debug alone will not switch the compiler to the new declarations. Change the resolution configuration, and use tsc --traceResolution to check which file the compiler selected. section 15.3.4 section 15.3.3
For TypeScript code intended for other projects, set compilerOptions.declaration to true to generate declaration files alongside compiled JavaScript. The files preserve type information for TypeScript consumers without preventing regular JavaScript use. In the demonstrated configuration, generation requires removing the JavaScript dependency and disabling allowJs; merely disabling allowJs while retaining an import of the JavaScript file can leave a missing runtime file. section 15.4
