Custom Type Guards
In this page:
Basic Type Predicate
A type predicate uses the form parameterName is Type as its return type annotation — the function body should return a boolean that genuinely and accurately checks whether the value matches that type.
Example: Basic Type Predicate
function isString(value: unknown): value is string {
return typeof value === "string";
}
const val: unknown = "hello";
if (isString(val)) console.log(val.toUpperCase());
Checking Object Shapes
Custom guards earn their keep most when working with unknown objects from external sources like API responses — check that every required property actually exists and has the right type before claiming the value matches an interface.
Example: Checking Object Shapes
interface User {
id: number;
name: string;
}
function isUser(value: any): value is User {
return typeof value?.id === "number" && typeof value?.name === "string";
}
const data: any = { id: 1, name: "Ravi" };
if (isUser(data)) console.log(data.name);
Guards for Union Types
A custom guard can distinguish between the members of a union type, which matters whenever different variants in that union carry different properties that plain equality checks can't tell apart.
Example: Guards for Union Types
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function isCircle(s: Shape): s is { kind: "circle"; radius: number } {
return s.kind === "circle";
}
const s: Shape = { kind: "circle", radius: 5 };
if (isCircle(s)) console.log(s.radius);
Generic Type Guards
Type guards can be written generically too — a generic guard can preserve the relationship between whatever input type it received and the more specific type it narrows down to.
Example: Generic Type Guards
function isOfType<T>(value: unknown, check: (v: unknown) => boolean): value is T {
return check(value);
}
const val: unknown = 42;
if (isOfType<number>(val, (v) => typeof v === "number")) console.log(val + 1);
Using Guards in Arrays
Custom guards work especially well passed straight into array methods like filter — TypeScript recognizes a predicate-shaped guard function and infers a narrower array type for the filtered result automatically.
Example: Using Guards in Arrays
const values: (string | null)[] = ["a", null, "b"];
function isString(v: string | null): v is string {
return v !== null;
}
const strings = values.filter(isString);
console.log(strings);
Chapter Quiz — Complete all 20 topics to unlock
0/20 topics done
Complete these topics first:
- TypeScript Advanced Types
- Mapped Types
- Conditional Types
- Custom Type Guards
- Assertion Functions
- Control Flow Analysis
- Exhaustiveness Checking
- Satisfies Operator
- Template Literal Types
- Utility Types - Partial
- Utility Types - Required
- Utility Types - Readonly
- Utility Types - Pick
- Utility Types - Omit
- Utility Types - Record
- Utility Types - Exclude and Extract
- Utility Types - NonNullable
- Utility Types - ReturnType
- Utility Types - Parameters
- TypeScript 5 Updates