Functions and Type NarrowingLesson 3.4
Type guards and custom type predicates in TypeScript
type predicate syntax, is keyword, user-defined type guards, discriminated unions, type assertion vs type guard
Type predicates
A type predicate is a return type of the form paramName is Type. When the function returns true, TypeScript narrows the argument to that type:
function isString(value: unknown): value is string {
return typeof value === "string";
}
function process(input: unknown) {
if (isString(input)) {
console.log(input.toUpperCase()); // string
}
}Discriminated unions
Add a shared literal property to distinguish union members — TypeScript narrows on it automatically:
interface Circle { kind: "circle"; radius: number; }
interface Square { kind: "square"; side: number; }
type Shape = Circle | Square;
function area(shape: Shape): number {
switch (shape.kind) {
case "circle": return Math.PI * shape.radius ** 2;
case "square": return shape.side ** 2;
}
}The discriminant property (kind) should be a string literal type, not a general string. This pattern is the most reliable way to handle heterogeneous unions and composes well with the never exhaustive check pattern from Lesson 1.5.
