TypeScript Assertion Functions
An assertion function is a function whose return type starts with the word `asserts`. A call that returns normally narrows a value for the code that follows it.
An asserts predicate narrows after the call
The function throws if the value is not a string. After the call, the checker treats the value as a string.
function assertText(v: string | number): asserts v is string {
if (typeof v !== "string") {
throw new Error("expected text");
}
}
const input: string | number = "workshop";
assertText(input);
console.log(input.toUpperCase());
console.log(input.length);The asserts condition form guards a nullable value
The caller passes the check itself as an argument. When the call returns, the passed condition is known to be true.
function assertTrue(condition: boolean, message: string): asserts condition {
if (!condition) {
throw new Error(message);
}
}
const labelText: string | null = "shipped";
assertTrue(labelText !== null, "label is missing");
console.log(labelText.toUpperCase());An aliased condition narrows in the branch
The typeof check is stored in a const boolean first. Testing that boolean still narrows the parameter inside each branch.
function describe(reading: string | number): void {
const isTextReading = typeof reading === "string";
if (isTextReading) {
console.log(reading.toUpperCase());
} else {
console.log(reading.toFixed(1));
}
}
describe("sensor-a");
describe(42);A failed assertion throws and can be caught
A failed check throws a plain Error at runtime. The catch block logs the message, and no string method ever runs on the number.
function assertText(v: string | number): asserts v is string {
if (typeof v !== "string") {
throw new Error("expected text");
}
}
const bad: string | number = 42;
try {
assertText(bad);
console.log("no error");
} catch (err) {
console.log(err instanceof Error ? err.message : "unknown error");
}Example
function assertText(v: string | number): asserts v is string {
if (typeof v !== "string") {
throw new Error("expected text");
}
}
const entryCode: string | number = "gate-9";
assertText(entryCode);
console.log(entryCode.replace("-", ":"));
console.log(entryCode.startsWith("gate"));Key points
- The form `asserts x is T` narrows x to T after the call returns.
- The form `asserts condition` narrows by the condition the caller passed in.
- An assertion function throws when its check fails, so later code never runs on a bad value.
- A const boolean built from a typeof check is an aliased condition.
- An aliased condition narrows inside the branch that tests it.
- Assertion functions narrow after the call, while aliased conditions narrow inside a branch.
In this example, assertText narrows entryCode to a string right after the call. String methods then run on it with no extra check in the main flow.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
A function is declared as `asserts v is string` and the call returns normally. What does the checker know about v after the call?