Assertion Functions (asserts)

Permanently narrow a type for the rest of the scope block.

TypeScript3 min readConcept 16 of 54

The limitation of Type Guards

Standard type guards and type predicates require you to wrap your code inside an if block. This can lead to deep nesting and messy code.

An 'Assertion Function' does something different: it tells TypeScript that if the function returns normally (without throwing an error), the type is permanently narrowed for the remainder of the current scope. No if block required.

Fail fast and keep code flat

This is a common pattern in testing (e.g. assert(user !== null)) and API validation.

By asserting conditions at the very top of a function and throwing an error if they fail, the rest of your function can proceed with a perfectly narrowed, safe type without any nesting.

The 'asserts' keyword

typescript // Notice the return type: function assertIsString(val: any): asserts val is string { if (typeof val !== "string") { throw new Error("Not a string!"); } } function process(id: string | number) { assertIsString(id); // No if-block needed! // TS knows 'id' is a string for the rest of the function. console.log(id.toUpperCase()); }

Try it

Watch how passing the assertIsString gatekeeper permanently locks the variable's type for the rest of the function scope.

function process(val: string | number) {

assertIsString(val);

// No if-block needed!
val.toUpperCase();
}
The Gatekeeper
Throws an error if val is not a string. Execution stops here on failure.
Locked Scope
Because execution reached this point, TS permanently narrows val: string for the rest of the block.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What is the primary difference between a Type Predicate ('val is string') and an Assertion Function ('asserts val is string')?

Remember this

  • Assertion functions use the asserts val is Type return signature.
  • They narrow a type for the remainder of the scope, preventing nested if blocks.
  • The function MUST throw an error if the condition fails.
  • TypeScript trusts the signature blindly, so ensure your internal logic is flawless.

Done with this concept?

Mark it complete to track your progress. No login needed.