patterntypescriptnoneModerate
Assertion Functions (asserts keyword) for Invariant Checking
Viewed 0 times
TypeScript 3.7+
assertsassertion functioninvariantnarrowingthrow on failure
Error Messages
Problem
Validation functions that throw on failure don't narrow the type after the call — TypeScript still treats the value as potentially invalid even though control flow proves it passed.
Solution
Use the 'asserts' return type to tell TypeScript that if the function returns normally, the condition holds.
function assertDefined<T>(val: T): asserts val is NonNullable<T> {
if (val === null || val === undefined) {
throw new Error(`Expected defined, got ${val}`);
}
}
function assertString(val: unknown): asserts val is string {
if (typeof val !== 'string') {
throw new TypeError(`Expected string, got ${typeof val}`);
}
}
const maybeUser: User | undefined = getUser();
assertDefined(maybeUser);
// Now TypeScript knows maybeUser is User (not undefined)
maybeUser.name; // No error
// Also works with Node's built-in assert:
import assert from 'node:assert';
assert(typeof value === 'string');
value.toUpperCase(); // narrowed to stringWhy
When a function has 'asserts condition' as its return type, TypeScript models the post-call state as the condition being true — similar to a type guard but for the unconditional path.
Gotchas
- Assertion functions must return 'void' or 'never' — they cannot return a value.
- TypeScript trusts your assertion unconditionally; an incorrect implementation creates unsound types.
- Node's assert module has built-in assertion function types in @types/node.
Revisions (0)
No revisions yet.