TypeScript asserts and Type Predicates in 2026: Writing Guards That Actually Narrow Correctly

This article was written with the assistance of AI, under human supervision and review.

Most TypeScript runtime validation breaks down because engineers write guards that compile but don't actually narrow types where it matters. The pattern that teams overlook is the distinction between type predicates that return boolean values and assertion functions that throw on failure—and choosing the wrong one creates silent bugs that surface in production.

The problem starts when developers write a function like isUser(value: unknown): boolean and expect TypeScript to understand what that boolean means. The compiler sees the function return true but has no idea that value is now safe to treat as a User type. Code that looks validated crashes at runtime because the type system never learned what the validation actually proved.

The fix is adding the type predicate syntax value is User to the return signature. This tells TypeScript that when the function returns true, the narrowed type holds in the calling scope. For throwing guards that never return on failure, the asserts keyword encodes that guarantee into the signature itself.