tsd: Check TypeScript Type Definitions
tsd is a utility designed for testing TypeScript type definitions, enabling developers to verify the correctness of their `.d.ts` files. The current stable version is 0.33.0, and the project maintains a relatively frequent release cadence, often updating to support newer TypeScript versions shortly after their release. It distinguishes itself by performing static analysis on `.test-d.ts` files, interpreting special assertion functions like `expectType`, `expectError`, and `expectAssignable` to check type compatibility without executing runtime code. This approach ensures that your type definitions accurately reflect your module's API and behavior, catching potential type-related regressions before they manifest as runtime errors or incorrect IDE IntelliSense. tsd is primarily used via its CLI, which automatically discovers project `package.json`, main type definition files, and test files within a configured directory.
Common errors
-
Argument of type '"foo"' is not assignable to parameter of type 'string | number'.
cause `expectType` received a value of type `string` but was expected to be `string | number`.fixThis error occurs because `expectType` requires an exact type match. If `string` is the actual and intended type, change `expectType<string | number>` to `expectType<string>`. If you want to check for assignability (a looser check), use `expectAssignable<string | number>('foo')`. -
No `package.json` found in current or specified directory.
cause `tsd` needs a `package.json` file in the directory where it's run, or in a specified project path, to locate the main type definition file and other configuration.fixEnsure you are running `tsd` from the root directory of your project, or explicitly pass the path to your project's root directory: `npx tsd /path/to/your/project`. -
No main type definition file found.
cause `tsd` could not automatically determine which `.d.ts` file to test. This usually happens if the `types` or `typings` field is missing from `package.json`, or if the main declaration file is not named `index.d.ts`.fixSpecify the path to your main declaration file in your `package.json` using the `types` field (e.g., `"types": "dist/index.d.ts"`), or ensure `index.d.ts` is in your project root or the specified path.
Warnings
- gotcha The `expectType` assertion performs strict type comparisons. For example, `expectType<string | number>(value: string)` will fail because `string` is assignable to, but not strictly identical to, `string | number`.
- breaking `tsd` frequently updates its internal TypeScript dependency to support the latest language features and diagnostics. This means that if your project uses an older, incompatible TypeScript version, `tsd`'s tests might fail or behave unexpectedly due to mismatches in compiler APIs or type inference.
- gotcha The `tsd` CLI is primarily designed to test an entire project's type definitions, relying on the presence of a `package.json` file and a main type declaration file. While it accepts a `path` argument, it's less suited for ad-hoc single-file type checks without a proper project structure.
Install
-
npm install tsd -
yarn add tsd -
pnpm add tsd
Imports
- expectType
const { expectType } = require('tsd')import { expectType } from 'tsd' - expectError
import expectError from 'tsd'
import { expectError } from 'tsd' - expectAssignable
import { expectAssignable } from 'tsd'
Quickstart
// index.d.ts
declare const concat: {
(value1: string, value2: string): string;
(value1: number, value2: number): number;
};
export default concat;
// index.test-d.ts
import { expectType, expectAssignable, expectError } from 'tsd';
import concat from '.';
// Assert that 'concat' with strings returns a string
expectType<string>(concat('foo', 'bar'));
// Assert that 'concat' with numbers returns a number
expectType<number>(concat(1, 2));
// Assert that 'concat' result is assignable to a union type (looser check)
expectAssignable<string | number>(concat('test', 'example'));
// Assert that 'concat' with incorrect types (e.g., booleans) throws a type error
expectError(concat(true, false));
// Example demonstrating top-level await with promises
async function testAsyncOperations() {
const asyncProcess = async (input: string): Promise<string> => Promise.resolve(`Processed: ${input}`);
expectType<Promise<string>>(asyncProcess('data'));
expectType<string>(await asyncProcess('data'));
}
testAsyncOperations(); // Execute the async test wrapper