What’s New
TSTyche 3

Release Notes

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

The detailed changelog can be found in TSTyche repository on GitHub (opens in a new tab).

TSTyche 3.0

TSTyche 3.0 ships with the new tsconfig option, support of a custom npm registry, the new omit() and pick() type utilities, support for reporters and plugins, programmatic usage refinements and performance improvements.

Requirements

The minimum required Node.js version is 18.19. It is recommended to use the latest Long Term Support (LTS) release.

Matchers

Breaking! The deprecated .toBeAssignable() and .toEqual() matchers are removed.

.toHaveProperty()

The .toHaveProperty() matcher now is able to check index signatures:

import { expect } from "tstyche";
 
expect<Record<string, unknown>>().type.toHaveProperty("sample");
 
expect<Record<number, unknown>>().type.not.toHaveProperty("sample");
 
interface DataProps {
  [key: `data-${string}`]: string;
}
 
expect<DataProps>().type.toHaveProperty("data-sample");

.toMatch()

The .toMatch() matcher is deprecated. The Omit and Pick utility types or the new omit() and pick() type utilities should be used for subtype testing.

.toRaiseError()

The .toRaiseError() matcher now takes regular expressions as well:

import { expect } from "tstyche";
 
interface Matchers<R, T = unknown> {
  [key: string]: (expected: T) => R;
}
 
// Pattern matching the error message
expect<Matchers>().type.toRaiseError(/between \d and \d type arguments/);
expect<Matchers>().type.toRaiseError(/generic .+ requires .+ type arguments/i);
 
// The exact error message
expect<Matchers>().type.toRaiseError(
  /^Generic type 'Matchers<R, T>' requires between 1 and 2 type arguments.$/,
);

Configuration

tsconfig

The look up strategy to be used to find the TSConfig file.

The following can be specified:

  • "findup", find the nearest tsconfig.json that includes a particular test file,
  • "ignore", do not look for any tsconfig.json and use the defaults,
  • or, if a path is specified, simply load tsconfig.json from that path.
{
  "tsconfig": "./tsconfig.test.json"
}

If TSConfig file is not found, or is ignored, or does not include a test file in question, the default compiler options will be set.

Environment Variables

Breaking! The TSTYCHE_TYPESCRIPT_PATH environment variable is removed. Use TSTYCHE_TYPESCRIPT_MODULE instead.

TSTYCHE_NPM_REGISTRY

The base URL of the npm registry (opens in a new tab) to use.

TSTYCHE_TYPESCRIPT_MODULE

TSTYCHE_TYPESCRIPT_MODULE is the new name of TSTYCHE_TYPESCRIPT_PATH. The value is now resolved using the import.meta.resolve() (opens in a new tab) function.

Type Utilities

TypeScript ships utility types like Omit or Pick that reshape types. They can also be useful when testing types. If you are testing types of expressions, use the omit() or pick() type utilities to have same results.

The utilities only reshape types. At runtime they return the same object that was passed as an argument.

omit()

The omit() type utility reshapes type of the given object by removing the specified keys:

import { expect, omit, pick } from "tstyche";
 
class Queue<T> {
  entries: Array<T> = [];
 
  get size(): number {
    return this.entries.length;
  }
 
  enqueue(item: T): void {
    this.entries.push(item);
  }
}
 
expect(omit(new Queue(), "enqueue", "entries")).type.toBe<{
  readonly size: number;
}>();
 
// Equivalent to the 'Omit' utility type
expect<Omit<Queue<string>, "enqueue" | "entries">>().type.toBe<{
  readonly size: number;
}>();

pick()

The pick() type utility reshapes type of the given object by keeping only the specified keys:

import { expect, omit, pick } from "tstyche";
 
class Queue<T> {
  entries: Array<T> = [];
 
  get size(): number {
    return this.entries.length;
  }
 
  enqueue(item: T): void {
    this.entries.push(item);
  }
}
 
expect(pick(new Queue(), "size")).type.toBe<{ readonly size: number }>();
 
// Equivalent to the 'Pick' utility type
expect<Pick<Queue<string>, "size">>().type.toBe<{ readonly size: number }>();

Reporters

The reporters allow to customize output of TSTyche. By default, the built-in list and summary reporters are used.

A custom reporter is a class that implements the on() method:

export default class CustomReporter {
  /**
   * @param {import("tstyche/tstyche").Event} event
   */
  on([event, payload]) {
    if (event === "run:start") {
      console.info("Hello from custom reporter!");
 
      for (const task of payload.result.tasks) {
        console.info(task.filePath);
      }
    }
  }
}

To learn more, see the Reporters page.

Plugins

The plugins allow to change behavior of TSTyche.

A plugin is an object with one or more hooks:

/**
 * @type {import("tstyche/tstyche").Plugin}
 */
export default {
  name: "example-plugin",
 
  config(resolvedConfig) {
    return { ...resolvedConfig, testFileMatch: [] };
  },
 
  async select() {
    return await getTestFilesSomehow(this.resolvedConfig);
  },
};

In this example, the config hook disables test file look up and the select hook returns a list of test files.

To learn more, see the Plugins page.

Programmatic Usage

This release also ships with refined programmatic API.

import { Config, Runner } from "tstyche/tstyche";
 
const resolvedConfig = Config.resolve();
const runner = new Runner(resolvedConfig);
 
 
await runner.run(["./typetests/toBeNumber.tst.ts"]);

To learn more, see the Programmatic Usage page.