Type Predicates and Assertion Functions
A user-defined type predicate returns a boolean with a type annotation such as value is User. When the function returns true, TypeScript narrows the checked value. Assertion functions use an asserts value is User return annotation and throw or otherwise fail if the condition is not met.
These annotations are promises made by the implementation. If the implementation returns true without checking the required fields, the compiler may trust an incorrect predicate. Keep validators small, test them, and prefer schema libraries for complex nested inputs.
A simple type predicate
type User = { id: string; name: string };
function isUser(value: unknown): value is User {
if (typeof value !== "object" || value === null) return false;
const candidate = value as Record<string, unknown>;
return typeof candidate.id === "string"
&& typeof candidate.name === "string";
}💡 The predicate checks the fields that the declared
User type requires. A cast is used only to inspect the object after checking it is non-null and object-like; a production validator may need more robust handling for special objects.Key Takeaways
- Type predicates communicate narrowing to the compiler.
- The implementation must genuinely prove the predicate.
- Complex nested data benefits from dedicated runtime schemas.
Knowledge Check
What does the return annotation `value is User` communicate?