Skip to Content
ReferenceExpect API

Expect API

TSTyche includes the expect flavoured assertions to compare types.

TSTyche uses TypeScript’s API to infer types of expressions. For a reminder of some nuanced aspects of the inference, see the Type Inference page.

expect()

The expect() function builds an assertion. It must be followed by the .type modifier and a matcher. Optionally, a run mode flag can be appended. expect() can be nested inside code.


Signatures. The source type can be provided either as a type argument or inferred from an expression:

expect<Source>() expect(source: unknown)

Run Mode Flags

To select assertions to run, append the run mode flags to the expect() function. The flags are inherited from the parent.

.only

Marks an assertion as focused. When there are focused groups, tests or assertions in a file, only those will run.

.skip

Marks an assertion as skipped. The test runner will ignore anything skipped and will suppress any type errors raised by the expressions or types passed to the expect() or a matcher function.

Matchers

A matcher is the final element in the assertion chain. It defines the condition to check.

.not

To negate a matcher, prepend .not before it:

import { expect } from "tstyche"; expect<string>().type.toBe<string>(); expect<number>().type.not.toBe<string>();

.toAcceptProps()

Checks if the JSX component accepts the given props.

This is a work in progress feature. Generic components are not yet supported.

import { , } from "tstyche"; interface ButtonProps { : string; ?: "reset" | "submit"; } function ({ , }: ButtonProps) { return < ={}>{}</>; } ("accepts props?", () => { ()..({ : "Send" }); ()..({ : "Clear", : "reset" as }); ()...({ : "Download", : "button" as }); ()...({}); });

Signatures. The props type can be provided either as a type argument or inferred from an expression:

.toAcceptProps<Target>() .toAcceptProps(target: unknown)

.toBe()

Checks if the source type is the same as the target type.

import { } from "tstyche"; type <> = { [ in keyof ]+?: [] | <[]>; }; type <> = & { : boolean }; <<<{ : string }>>>()..<{ ?: string | <string>; : boolean; }>();

The types are compared programmatically by walking their structure. As you see in the above example, the matcher treats { a: string } & { b: number } and { a: string; b: number } as equivalent.

The implementation allows granular checks of every detail. For example, it distinguishes between types with and without the NoInfer marker:

import { } from "tstyche"; const = <>(: ) => ; const = <>(: <>) => ; (("kiwi"))..<"kiwi">(); (("kiwi"))..<unknown>(); // Identical input results in a different return type, // therefore the matcher treats these signatures as non-equivalent ()...();

Signatures. The target type can be provided either as a type argument or inferred from an expression:

.toBe<Target>() .toBe(target: unknown)

.toBeApplicable

Checks if the decorator function can be applied to a class or a class member.

Differently from other matchers, .toBeApplicable must be used as a decorator:

import { , } from "tstyche"; function <, extends (: , ...: any) => any>( : , : <, >, ) { // ... } ("bind", () => { class { #name: string; constructor(: string) { this.#name = ; } @(()..) // <-- and here it is! () { return `Hello, my name is ${this.#name}.`; } } });

.toBeAssignableFrom()

Checks if the source type is assignable from the target type.

import { , } from "tstyche"; type <> = | <>; ("Awaitable", () => { <<string>>()..("abc"); <<string>>()..(.("abc")); <<string>>()...(123); <<string>>()...(.(123)); });

Use the .toBeAssignableTo() matcher to test the relationship in the reverse direction.

As the best practice, always keep the type under test on the left hand side of the assertion. This makes the test easier to read:

- expect<Set<string>>.type.toBeAssignableFrom(new Set(["abc"])); + expect(new Set(["abc"])).type.toBeAssignableTo<Set<string>>();

Signatures. The target type can be provided either as a type argument or inferred from an expression:

.toBeAssignableFrom<Target>() .toBeAssignableFrom(target: unknown)

.toBeAssignableTo()

Checks if the source type is assignable to the target type.

import { , } from "tstyche"; ("Set", () => { (new (["abc"]))..<<string>>(); (new ([123]))..<<number>>(); (new ([123, "abc"]))...<<string>>(); (new ([123, "abc"]))...<<number>>(); });

Use the .toBeAssignableFrom() matcher to test the relationship in the reverse direction.

As the best practice, always keep the type under test on the left hand side of the assertion. This makes the test easier to read:

- expect("abc").type.toBeAssignableTo<Awaitable<string>>(); + expect<Awaitable<string>>().type.toBeAssignableFrom("abc");

Signatures. The target type can be provided either as a type argument or inferred from an expression:

.toBeAssignableTo<Target>() .toBeAssignableTo(target: unknown)

.toBeCallableWith()

Checks if a function is callable with the given arguments.

import { , } from "tstyche"; function < extends { : number }>(: , : ) { return . === .; } ("isSameLength", () => { (([1, 2], [1, 2, 3]))..<boolean>(); (("one", "two"))..<boolean>(); ()...(1, 2); ()...("zero", [123]); (<string | <number>>)..("zero", [123]); });

Signature. The matcher accepts zero or more arguments:

.toBeCallableWith(...args: Array<unknown>)

.toBeConstructableWith()

Checks if a class is constructable with the given arguments.

import { , } from "tstyche"; class <> { : ; : ; constructor(: , : ) { this. = ; this. = ; } } ("Pair", () => { ()..("sun", "moon"); ()..(true, false); ()...("five", 10); (<number | string>)..("five", 10); ()...(); ()...("nope"); });

Signature. The matcher accepts zero or more arguments:

.toBeConstructableWith(...args: Array<unknown>)

.toHaveProperty()

Checks if a property key exists on the source type.

import { , } from "tstyche"; type <> = { [ in keyof as <, "setup" | "teardown">]: []; }; interface Sample { [: `data-${string}`]: string; ?: boolean | undefined; : (: string, : number) => void; : () => void; : () => void; } ("Worker", () => { <<Sample>>()..("data-sample"); <<Sample>>()..("isBusy"); <<Sample>>()..("runTest"); <<Sample>>()...("setup"); <<Sample>>()...("teardown"); });

Signature. The key argument can be a string, number or symbol:

.toHaveProperty(key: string | number | symbol)

.toRaiseError()

Checks if the source type raises an error.

import { , } from "tstyche"; interface <, = unknown> { [: string]: (: ) => ; } ("Matchers", () => { <<void, string>>()...(); <<void>>()...(); <>()..("requires between 1 and 2 type arguments"); });

If the source type raises several errors, the matcher will require an argument for each of them.

TSTyche is able to check error messages suppressed by the // @ts-expect-error directives in the test files. It is recommended to use the // @ts-expect-error instead of .toRaiseError(). To learn more, see the documentation of the checkSuppressedErrors option.

To indicate the purpose of a test, use matchers like .toBeCallableWith() or .toHaveProperty() instead of expecting an error.


Signature. The matcher accepts one or more substrings, numeric codes or regular expressions:

.toRaiseError(...target: Array<string | number | RegExp>)
Last updated on