zhaochy
zhaochy

Reputation: 774

How to write tests for typescript typing definition?

We have a Node.js lib, recently we added a type definitions for it.

But how could I test the type definition?

Upvotes: 15

Views: 8749

Answers (4)

TrevTheDev
TrevTheDev

Reputation: 2747

An option if one is only checking types is to use syntax highlighting. In a test file I do something like this:

const t=(result:true)=>console.log(result)
const f=(result:false)=>console.log(result)

type MyType = string

t(false as ( 'dog' extends MyType ? true : false ))
t(false as ( 1 extends MyType ? true : false ))
f(true as ( 1 extends MyType ? true : false ))

let x : 'a' | 'b'

t(false as ( 'a' extends typeof x ? true : false ))
t(false as ( 'b' extends typeof x ? true : false ))
t(false as ( 'c' extends typeof x ? true : false ))

code with syntax highlight

The structure is: t(false as ( <<<test>>> extends <<<type to test>>> ? true ; false ))

Upvotes: 1

Aleksi
Aleksi

Reputation: 5056

Microsoft's dtslint is a handy tool for testing type declarations. As the name suggests its a static analysis tool that doesn't run your test files but only type-checks them. You can additionally supplement tests with comment-based assertions that the tool evaluates:

import { f } from "my-lib"; // f is(n: number) => void

// $ExpectType void
f(1);

// Can also write the assertion on the same line.
f(2); // $ExpectType void

// $ExpectError
f("one");

tsd is another tool with similar assertions:

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

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

Also as of Typescript 3.9 you can use the built-in // @ts-expect-error comment:

When a line is prefixed with a // @ts-expect-error comment, TypeScript will suppress that error from being reported; but if there’s no error, TypeScript will report that // @ts-expect-error wasn’t necessary. (source)

Upvotes: 9

Nurbol Alpysbayev
Nurbol Alpysbayev

Reputation: 21971

I wrote a lib for this purpose, check it out: https://github.com/qurhub/qur-typetest

The typescript compiler only checks that types are correct, but it is not capable of checking whether your type fails when you expect it to fail.

So, in the mentioned library you write tests like this:

const str: string = "foo"

in order to ensure type string compiles when assigned to value "foo". And you write tests like this:

// tt:throws:Type '1' is not assignable to type 'string'.
const str: string = 1

in order to ensure type string fails to compile when assigned to value 1.

Of course, instead of string you should test your actual complex types, like, for example, mapped types.

Upvotes: 3

Pasi
Pasi

Reputation: 2674

The tests in DefinitelyTyped are files that are supposed to type-check correctly. So the test exercises different parts of the API, and it's run through the compiler (but the generated JavaScript code is not actually executed). See, for example, tests for @types/express.

For your own project, I guess you'd write a similar test file yourself, and compile it as part of your build (if it compiles, then the test succeeds). Of course, if you already have existing TypeScript code using those type definitions, that might be sufficient test.

Typings-checker is a proof-of-concept that also allows testing failures (incorrectly typed code should not compile).

Upvotes: 7

Related Questions