npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tsd

v0.31.0

Published

Check TypeScript type definitions

Downloads

743,429

Readme

tsd CI

Check TypeScript type definitions

Install

npm install --save-dev tsd

Overview

This tool lets you write tests for your type definitions (i.e. your .d.ts files) by creating files with the .test-d.ts extension.

These .test-d.ts files will not be executed, and not even compiled in the standard way. Instead, these files will be parsed for special constructs such as expectError<Foo>(bar) and then statically analyzed against your type definitions.

The tsd CLI will search for the main .d.ts file in the current or specified directory, and test it with any .test-d.ts files in either the same directory or a test sub-directory (default: test-d):

[npx] tsd [path]

Use tsd --help for usage information. See Order of Operations for more details on how tsd finds and executes tests.

Note: the CLI is primarily used to test an entire project, not a specific file. For more specific configuration and advanced usage, see Configuration and Programmatic API.

Usage

Let's assume we wrote a index.d.ts type definition for our concat module.

declare const concat: {
	(value1: string, value2: string): string;
	(value1: number, value2: number): string;
};

export default concat;

In order to test this definition, add a index.test-d.ts file.

import concat from '.';

concat('foo', 'bar');
concat(1, 2);

Running npx tsd as a command will verify that the type definition works correctly.

Let's add some extra assertions. We can assert the return type of our function call to match a certain type.

import {expectType} from 'tsd';
import concat from '.';

expectType<string>(concat('foo', 'bar'));
expectType<string>(concat(1, 2));

The tsd command will succeed again.

We change our implementation and type definition to return a number when both inputs are of type number.

declare const concat: {
	(value1: string, value2: string): string;
	(value1: number, value2: number): number;
};

export default concat;

If we don't change the test file and we run the tsd command again, the test will fail.

Strict type assertions

Type assertions are strict. This means that if you expect the type to be string | number but the argument is of type string, the tests will fail.

import {expectType} from 'tsd';
import concat from '.';

expectType<string>(concat('foo', 'bar'));
expectType<string | number>(concat('foo', 'bar'));

If we run tsd, we will notice that it reports an error because the concat method returns the type string and not string | number.

If you still want loose type assertion, you can use expectAssignable for that.

import {expectType, expectAssignable} from 'tsd';
import concat from '.';

expectType<string>(concat('foo', 'bar'));
expectAssignable<string | number>(concat('foo', 'bar'));

Top-level await

If your method returns a Promise, you can use top-level await to resolve the value instead of wrapping it in an async IIFE.

import {expectType, expectError} from 'tsd';
import concat from '.';

expectType<Promise<string>>(concat('foo', 'bar'));

expectType<string>(await concat('foo', 'bar'));

expectError(await concat(true, false));

Order of Operations

When searching for .test-d.ts files and executing them, tsd does the following:

  1. Locates the project's package.json, which needs to be in the current or specified directory (e.g. /path/to/project or process.cwd()). Fails if none is found.

  2. Finds a .d.ts file, checking to see if one was specified manually or in the types field of the package.json. If neither is found, attempts to find one in the project directory named the same as the main field of the package.json or index.d.ts. Fails if no .d.ts file is found.

  3. Finds .test-d.ts and .test-d.tsx files, which can either be in the project's root directory, a specific folder (by default /[project-root]/test-d), or specified individually programatically or via the CLI. Fails if no test files are found.

  4. Runs the .test-d.ts files through the TypeScript compiler and statically analyzes them for errors.

  5. Checks the errors against assertions and reports any mismatches.

Assertions

expectType<T>(expression: T)

Asserts that the type of expression is identical to type T.

expectNotType<T>(expression: any)

Asserts that the type of expression is not identical to type T.

expectAssignable<T>(expression: T)

Asserts that the type of expression is assignable to type T.

expectNotAssignable<T>(expression: any)

Asserts that the type of expression is not assignable to type T.

expectError<T = any>(expression: T)

Asserts that expression throws an error. Will not ignore syntax errors.

expectDeprecated(expression: any)

Asserts that expression is marked as @deprecated.

expectNotDeprecated(expression: any)

Asserts that expression is not marked as @deprecated.

printType(expression: any)

Prints the type of expression as a warning.

Useful if you don't know the exact type of the expression passed to printType() or the type is too complex to write out by hand.

expectNever(expression: never)

Asserts that the type and return type of expression is never.

Useful for checking that all branches are covered.

expectDocCommentIncludes<T>(expression: any)

Asserts that the documentation comment of expression includes string literal type T.

Configuration

tsd is designed to be used with as little configuration as possible. However, if you need a bit more control, a project's package.json and the tsd CLI offer a limited set of configurations.

For more advanced use cases (such as integrating tsd with testing frameworks), see Programmatic API.

Via package.json

tsd uses a project's package.json to find types and test files as well as for some configuration. It must exist in the path given to tsd.

For more information on how tsd finds a package.json, see Order of Operations.

Test Directory

When you have spread your tests over multiple files, you can store all those files in a test directory called test-d. If you want to use another directory name, you can change it in your project's package.json:

{
	"name": "my-module",
	"tsd": {
		"directory": "my-test-dir"
	}
}

Now you can put all your test files in the my-test-dir directory.

Custom TypeScript Config

By default, tsd applies the following configuration:

{
	"strict": true,
	"jsx": "react",
	"target": "es2020",
	"lib": [
		"es2020",
		"dom",
		"dom.iterable"
	],
	"module": "commonjs",
	"esModuleInterop": true,
	"noUnusedLocals": false,
	// The following options are set and are not overridable.
	// Set to `nodenext` if `module` is `nodenext`, `node16` if `module` is `node16` or `node` otherwise.
	"moduleResolution": "node" | "node16" | "nodenext",
	"skipLibCheck": false
}

These options will be overridden if a tsconfig.json file is found in your project. You also have the possibility to provide a custom config by specifying it in package.json:

{
	"name": "my-module",
	"tsd": {
		"compilerOptions": {
			"strict": false
		}
	}
}

Default options will apply if you don't override them explicitly. You can't override the moduleResolution or skipLibCheck options.

Via the CLI

The tsd CLI is designed to test a whole project at once, and as such only offers a couple of flags for configuration.

--typings

Alias: -t

Path to the type definition file you want to test. Same as typingsFile.

--files

Alias: -f

An array of test files with their path. Same as testFiles.

Programmatic API

You can use the programmatic API to retrieve the diagnostics and do something with them. This can be useful to run the tests with AVA, Jest or any other testing framework.

import tsd from 'tsd';

const diagnostics = await tsd();

console.log(diagnostics.length);
//=> 2

You can also make use of the CLI's formatter to generate the same formatting output when running tsd programmatically.

import tsd, {formatter} from 'tsd';

const formattedDiagnostics = formatter(await tsd());

tsd(options?)

Retrieve the type definition diagnostics of the project.

options

Type: object

cwd

Type: string
Default: process.cwd()

Current working directory of the project to retrieve the diagnostics for.

typingsFile

Type: string
Default: The types property in package.json.

Path to the type definition file you want to test. This can be useful when using a test runner to test specific type definitions per test.

testFiles

Type: string[]
Default: Finds files with .test-d.ts or .test-d.tsx extension.

An array of test files with their path. Uses globby under the hood so that you can fine tune test file discovery.