Type-Level Testing: expectTypeOf and Static Type System Assertions
Testing complex TypeScript generics, utility types, and type inference without runtime overhead.
Part 11 in Series — Catch up on the previous article: In-Source Testing & Zero-Overhead Production Dead Code Elimination (Part 10) before diving into this post.
Complex TypeScript codebases often contain heavy type manipulations: generics, conditional types, and utility wrappers. Standard unit tests only verify runtime behavior, leaving static type regressions unchecked.
Vitest includes native type testing utilities via expectTypeOf() and assertType().
import { test, expectTypeOf } from 'vitest';
import type { UserResponse } from './types';
function createStore<T>(initial: T) {
return { get: () => initial };
}
test('verifies type inference', () => {
const store = createStore({ id: '101', active: true });
// Type assertions (checked by TypeScript at build time)
expectTypeOf(store.get()).toEqualTypeOf<{ id: string; active: boolean }>();
expectTypeOf(store.get().id).toBeString();
expectTypeOf(store.get().active).toBeBoolean();
});
Running Typechecks in CLI
You can execute type tests in CI/CD using Vitest’s typecheck command:
vitest typecheck
This runs tsc under the hood via Vitest’s runner, checking type assertions without spawning Node execution runtime.
Part 12: Coverage Engines: Bytecode Coverage via V8 AST Counters vs AST Instrumentation with Istanbul
Continue to Part 12 →