← Back to TypeScript Course | Chapter 8: Advanced Types | Lesson 4 of 20

Custom Type Guards

A custom type guard is a function that tells TypeScript whether a value has a particular type. A predicate return type such as value is User lets TypeScript narrow the value after the guard succeeds.

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

typescript
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

typescript
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

typescript
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

typescript
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

typescript
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);

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.