SyntaxStudy
Sign Up
TypeScript typeof, instanceof, and in Guards
TypeScript Beginner 1 min read

typeof, instanceof, and in Guards

Type guards are expressions that perform a runtime check and narrow the type of a variable within the scope where the check is true. TypeScript's control flow analysis recognises several built-in type guard patterns automatically. The typeof operator narrows to one of the seven primitive type strings. The instanceof operator narrows to the class or constructor function on the right side. The in operator checks whether a property exists on an object and serves as a type guard for distinguishing between object types that have different property sets. This is particularly useful for discriminating between variants in a union when they share some properties but not others. The key must be a string literal or string literal union for TypeScript to narrow correctly. Truthiness narrowing is perhaps the most common form of type guard. When you check a value in an if condition, TypeScript removes null, undefined, 0, empty string, and false from the type within the truthy branch. Equality narrowing — checking if a value equals a specific literal — is another powerful form that TypeScript understands automatically.
Example
// typeof guard — primitives
function processInput(input: string | number | boolean): string {
    if (typeof input === "string")  return input.toUpperCase();
    if (typeof input === "number")  return input.toFixed(2);
    return input ? "YES" : "NO";
}

// instanceof guard — classes
class ValidationError extends Error {
    constructor(public field: string, message: string) {
        super(message);
        this.name = "ValidationError";
    }
}

class NetworkError extends Error {
    constructor(public statusCode: number, message: string) {
        super(message);
        this.name = "NetworkError";
    }
}

function handleError(err: Error): void {
    if (err instanceof ValidationError) {
        console.error(`Validation failed on field: ${err.field}`);
    } else if (err instanceof NetworkError) {
        console.error(`HTTP ${err.statusCode}: ${err.message}`);
    } else {
        console.error("Unknown error:", err.message);
    }
}

// 'in' guard — object shapes
interface Square   { kind: "square";   side: number }
interface Triangle { kind: "triangle"; base: number; height: number }

type Polygon = Square | Triangle;

function describePolygon(p: Polygon): string {
    if ("side" in p) return `Square with side ${p.side}`;
    return `Triangle with base ${p.base}`;
}

// Truthiness narrowing
function greet(name: string | null | undefined): string {
    if (name) return `Hello, ${name}!`; // name is string here
    return "Hello, stranger!";
}