TypeScript Type Guards

VerifiedSafe

Narrow union types safely using type guards, assertion functions, and control flow in TypeScript.

Sby Skills Guide Bot
DevelopmentIntermediate
7/26/2026
Claude CodeCursorWindsurfCopilotCodex
#typescript#type-guards#type-narrowing#type-safety#type-inference

Recommended for

Automated summary

This skill explains how to narrow TypeScript union types using type guards, assertion functions, and control flow analysis.

Strengths

  • Covers the main narrowing techniques: typeof, instanceof, the in operator, is predicates, asserts functions, and discriminated unions
  • Provides complete, directly reusable code examples for each technique
  • Clarifies the important distinction between a plain boolean return, an is predicate, and an asserts function
  • Shows how to safely validate unknown values from APIs and how to properly type Array.filter results

Limitations

  • The supplied content is truncated: the Details section cuts off mid-word at "Trut"
  • Does not cover schema validation libraries (Zod, io-ts, valibot) or how they combine with type guards
  • Omits advanced topics such as type-level tests or complex generic predicates
When to use it

Use it when you need to narrow a union type, validate external data, or replace unsafe as assertions with safe runtime checks in TypeScript.

When not to use it

Skip it if your project is plain JavaScript or already relies on a schema validation library that handles narrowing for you.

Security analysis

Safe
Quality score88/100

The skill is a static reference document about TypeScript type guards and contains only code examples and explanations. It declares no tools and performs no execution, network, or file operations, so there is no meaningful security risk.

No concerns found

How this analysis is made

Examples

Narrow a union safely
Refactor this function so it takes a Cat | Dog union and uses a custom `is` predicate type guard instead of an `as` cast, then call the right method in each branch.
Validate unknown API data
Write an isUser type guard that accepts `unknown` and checks id and email are strings, building on an isRecord helper, so the parsed JSON response is safely narrowed.
Typed array filtering
This filter returns (string | null)[] but I want string[] — rewrite it using a type predicate in the filter callback.

TypeScript Type Guards

Narrow union types safely using type guards, assertion functions, and control flow

When to Use

  • Narrowing union types to access type-specific properties
  • Validating unknown data from APIs or user input
  • Replacing unsafe type assertions (as) with safe runtime checks
  • Creating reusable narrowing functions for domain types

Instructions

  1. typeof guard for primitives:
function format(value: string | number): string {
  if (typeof value === 'string') {
    return value.toUpperCase(); // Narrowed to string
  }
  return value.toFixed(2); // Narrowed to number
}
  1. instanceof guard for class instances:
function handleError(error: Error | string): string {
  if (error instanceof Error) {
    return error.message; // Narrowed to Error
  }
  return error; // Narrowed to string
}
  1. Custom type guard with is predicate:
interface Cat {
  meow(): void;
}
interface Dog {
  bark(): void;
}

function isCat(animal: Cat | Dog): animal is Cat {
  return 'meow' in animal;
}

function interact(animal: Cat | Dog) {
  if (isCat(animal)) {
    animal.meow(); // Narrowed to Cat
  } else {
    animal.bark(); // Narrowed to Dog
  }
}
  1. Narrowing with in operator:
type ApiResponse = { status: 'success'; data: User } | { status: 'error'; message: string };

function handle(response: ApiResponse) {
  if ('data' in response) {
    console.log(response.data); // Narrowed to success variant
  }
}
  1. Assertion function — narrows or throws:
function assertDefined<T>(value: T | null | undefined, name: string): asserts value is T {
  if (value == null) {
    throw new Error(`Expected ${name} to be defined`);
  }
}

function process(user: User | null) {
  assertDefined(user, 'user');
  // user is narrowed to User after this line
  console.log(user.name);
}
  1. Narrow unknown values safely:
function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

function isUser(value: unknown): value is User {
  return isRecord(value) && typeof value.id === 'string' && typeof value.email === 'string';
}
  1. Array filtering with type guards:
const items: (string | null)[] = ['a', null, 'b', null, 'c'];

// Without type guard: (string | null)[]
const filtered = items.filter((x) => x !== null);

// With type guard: string[]
const filtered = items.filter((x): x is string => x !== null);
  1. Discriminated union narrowing:
type Shape = { kind: 'circle'; radius: number } | { kind: 'rect'; width: number; height: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'rect':
      return shape.width * shape.height;
  }
}

Details

Type guards are runtime checks that TypeScript uses to narrow types in subsequent code. They bridge the gap between TypeScript's static type system and JavaScript's dynamic runtime.

Control flow analysis: TypeScript tracks type narrowing through if/else, switch, return, throw, and assignment. After a type guard condition, the type is narrowed in the true branch and the complement is narrowed in the else branch.

is predicates vs boolean returns: A function returning boolean does not narrow types at the call site. A function returning x is Type does. The is predicate is a promise to the compiler — if you return true, the value IS that type.

Assertion functions (asserts x is T) narrow the type AFTER the function call returns. If the assertion fails, the function must throw. This is useful for precondition checks at the top of functions.

asserts vs is:

  • is — used in conditions (if, filter). Returns boolean.
  • asserts — used as a statement. Throws on failure. Narrows for subsequent code.

Truthiness narrowing: TypeScript narrows if (value) to exclude null, undefined, 0, '', and false. This is convenient but can exclude valid falsy values — use explicit != null when 0 or '' are valid.

Trade-offs:

  • Custom type guards with is put the burden of correctness on the developer — an incorrect guard silently misnarrows
  • instanceof does not work across iframes, realms, or serialized objects
  • Assertion functions cannot be used in expression position — they must be standalone statements
  • Deep narrowing of nested objects requires multiple guard calls or a comprehensive validation library like Zod

Source

https://typescriptlang.org/docs/handbook/2/narrowing.html

Process

  1. Read the instructions and examples in this document.
  2. Apply the patterns to your implementation, adapting to your specific context.
  3. Verify your implementation against the details and edge cases listed above.

Harness Integration

  • Type: knowledge — this skill is a reference document, not a procedural workflow.
  • No tools or state — consumed as context by other skills and agents.

Success Criteria

  • The patterns described in this document are applied correctly in the implementation.
  • Edge cases and anti-patterns listed in this document are avoided.

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/typescript-type-guards-ms1aw5bo/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/typescript-type-guards-ms1aw5bo' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/typescript-type-guards-ms1aw5bo/download' --output '.skill-downloads/typescript-type-guards-ms1aw5bo/SKILL.md.part' && mv '.skill-downloads/typescript-type-guards-ms1aw5bo/SKILL.md.part' '.skill-downloads/typescript-type-guards-ms1aw5bo/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

This file does not provide a usable name/description header for this native procedure. It remains available to download and inspect; use the manual method below.

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/typescript-type-guards-ms1aw5bo/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills