Skip to Content
What’s NewTSTyche 4

Release Notes

This page lists breaking changes and notable new features. Please be sure to read the release notes before upgrading from a previous version.

The detailed changelog can be found in TSTyche repository on GitHub .

TSTyche 4.3

TSTyche 4.3 adds the new fixtureFileMatch configuration option.

Configuration

fixtureFileMatch

The list of glob patterns to match the fixture files.

TSTyche 4.2

TSTyche 4.2 adds glob brace expansion.

Configuration

testFileMatch

Brace expansion of comma-separated lists is now supported. For example, ["**/tests/*.{ts,tsx}"] or ["**/tests/*.ts{,x}"] both expand to ["**/tests/*.ts", "**/tests/*.tsx"].

TSTyche 4.1

TSTyche 4.1 adds the new checkSuppressedErrors configuration option.

Configuration

checkSuppressedErrors

Check errors suppressed by @ts-expect-error directives in the test files.

When this option is enabled, the runner reads the text after @ts-expect-error and checks if it matches the actual error message.

Compiler Options

The noUncheckedSideEffectImports compiler option is now enabled for TypeScript 5.6 and above.

TSTyche 4.0

TSTyche 4.0 ships with the new .toBeApplicable, .toBeCallableWith() and .toBeConstructableWith() matchers, support for template test files, enhanced protection against accidental any or never types and stricter default compiler options.

Requirements

Breaking! The minimum supported Node.js version is 20.9. It is recommended to use the latest LTS release .

TypeScript Versions

Breaking! Support for TypeScript <=4.6 is dropped. Only version 4.7 or above can be used for testing.

Matchers

Breaking! The deprecated .toMatch() matcher is removed.

Breaking! All primitive type matchers like .toBeString() or .toBeNumber() are removed. Use .toBe() instead:

import { expect } from "tstyche"; - expect<string>().type.toBeString(); + expect<string>().type.toBe<string>(); - expect<number>().type.toBeNumber(); + expect<number>().type.toBe<number>();

.toBeApplicable

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

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

import { expect, test } from "tstyche"; function bind<This, Value extends (this: This, ...args: any) => any>( target: Value, context: ClassMethodDecoratorContext<This, Value>, ) { // ... } test("bind", () => { class Fixture { #name: string; constructor(name: string) { this.#name = name; } @(expect(bind).type.toBeApplicable) // <-- used as a decorator here toString() { return `Hello, my name is ${this.#name}.`; } } });

.toBeCallableWith()

The new .toBeCallableWith() matcher checks if a function is callable with the given arguments.

import { expect, test } from "tstyche"; function isSameLength<T extends { length: number }>(a: T, b: T) { return a.length === b.length; } test("isSameLength", () => { expect(isSameLength([1, 2], [1, 2, 3])).type.toBe<boolean>(); expect(isSameLength("one", "two")).type.toBe<boolean>(); expect(isSameLength).type.not.toBeCallableWith(1, 2); expect(isSameLength).type.not.toBeCallableWith("zero", [123]); expect(isSameLength<string | Array<number>>).type.toBeCallableWith("zero", [123]); });

.toBeConstructableWith()

The new .toBeConstructableWith() matcher checks if a class is constructable with the given arguments.

import { expect, test } from "tstyche"; class Pair<T> { left: T; right: T; constructor(left: T, right: T) { this.left = left; this.right = right; } } test("Pair", () => { expect(Pair).type.toBeConstructableWith("sun", "moon"); expect(Pair).type.toBeConstructableWith(true, false); expect(Pair).type.not.toBeConstructableWith("five", 10); expect(Pair<number | string>).type.toBeConstructableWith("five", 10); expect(Pair).type.not.toBeConstructableWith(); expect(Pair).type.not.toBeConstructableWith("nope"); });

Conditional Tests

The // @tstyche if comment directive allows conditionally skipping an expect(), test() or describe():

import { expect, test } from "tstyche"; function isUint8Array(target: unknown): target is Uint8Array { return target instanceof Uint8Array; } test("isUint8Array", () => { const unknowns: Array<unknown> = []; // @tstyche if { target: [">=5.7"] } -- Before TypeScript 5.7, 'Uint8Array' was not generic expect(unknowns.filter(isUint8Array)).type.toBe<Array<Uint8Array<ArrayBufferLike>>>(); // @tstyche if { target: ["<5.7"] } expect(unknowns.filter(isUint8Array)).type.toBe<Array<Uint8Array>>(); });

Placing this directive at the top of the file applies the condition to the whole file.

Template Test Files

Template test files allow generating type tests programmatically.

To mark a test file as a template, add the // @tstyche template comment directive at the top. When the directive is found, the default export is interpreted as type test text.

For example, the following:

// @tstyche template -- For documentation, see: https://tstyche.org/guides/template-test-files let testText = `import { expect, test } from "tstyche"; `; for (const source of ["string", "number"]) { testText += `test("is ${source} a string?", () => { expect<${source}>().type.toBe<string>(); }); `; } export default testText;

is interpreted as:

import { expect, test } from "tstyche"; test("is string a string?", () => { expect<string>().type.toBe<string>(); }); test("is number a string?", () => { expect<number>().type.toBe<string>(); });

To learn more, see the Template Test Files page.

Thanks to @nikelborm  for the idea!

Configuration

checkSourceFiles

The checkSourceFiles configuration option is enabled by default.

rejectAnyType

The rejectAnyType configuration option is enabled by default.

rejectNeverType

The rejectNeverType configuration option is enabled by default.

Command Line

--fetch

--fetch is the new name of --install.

Compiler Options

If your project does not have a TSConfig file, default compiler options are now stricter:

{ "allowImportingTsExtensions": true, // not set for TypeScript 4.x "allowJs": true, "checkJs": true, "exactOptionalPropertyTypes": true, "jsx": "preserve", "module": "nodenext", "moduleResolution": "nodenext", "noUncheckedIndexedAccess": true, "resolveJsonModule": true, "strict": true, "target": "esnext", "verbatimModuleSyntax": true // not set for TypeScript 4.x }
Last updated on