Expect Errors
When testing invalid code, use the ability matchers to avoid the @ts-expect-error trap. If the error message matters, TSTyche can also verify what @ts-expect-error suppresses.
The @ts-expect-error Trap
The use of @ts-expect-error directives in type tests is a popular approach to test that a certain piece of code is invalid.
In the following example type test, the import was lost during refactoring. The code will compile and the test will appear to pass, although the actual error is Cannot find name 'add':
// @ts-expect-error Requires 2 arguments
add(2);Because @ts-expect-error suppresses any errors on the following line, type tests using it cast too wide a net. This results in misleading tests. The APIs under test might change, be renamed, or be removed, yet the tests will fail to catch regressions.
The Ability Matchers
TSTyche ships with the ability matchers like .toBeCallableWith() that address the problem described above:
import { } from "tstyche";
(add)...(2);The ability matchers communicate the intent of a test and are designed to handle even the most complex cases like generic types:
import { , } from "tstyche";
type = <, extends keyof >(: , : ) => [];
const = {
: "Alice",
: "alice@example.com",
};
("FormFieldGetter", () => {
<>()..(, "name");
<>()...(, "age");
});The following ability matchers are available:
.toAcceptProps()checks if a JSX component accepts the given props.toBeApplicablechecks if a decorator is applicable to the given class or class member.toBeCallableWith()checks if a function is callable with the given arguments.toBeConstructableWith()checks if a class is constructable with the given arguments.toHaveProperty()checks if a type has the given property
The available matchers cover most of the cases where invalid code is being tested. If you find something missing, please open an issue.
How They Work
The ability matchers work by erasing their syntax.
expect(add).type.not.toBeCallableWith(2);
(add) (2); // after erasingThe test file is checked for type errors, the matcher syntax is erased (similar to the above example) and the code is checked again. If there are new errors, the assertion is reported as failing or, when negated with .not, as passing.
In a way, the ability matchers are similar to @ts-expect-error, but are far more precise and expressive.