Suggest an editImprove this articleRefine the answer for “What is a "type guard"?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A **type guard** is a logical expression or function that helps TypeScript refine the type of a variable in a particular branch of code. **Key point:** the main kinds are `typeof` (for primitives), `instanceof` (for classes), `in` (checking for a property), and custom `value is Type` functions.Shown above the full answer for quick recall.Answer (EN)Image## What a Type Guard is A **type guard** is a **logical expression or function** that helps TypeScript **refine the type of a variable** in a particular branch of code. > Put simply: a type guard is a way to "tell the compiler who I really am". --- ### Example without a type guard ```javascript function printId(id: string | number) { console.log(id.toUpperCase()); // Error - id might be a number } ``` TypeScript doesn't know whether `id` is a `string` or a `number`. --- ### With a Type Guard ```javascript function printId(id: string | number) { if (typeof id === "string") { // here id: string console.log(id.toUpperCase()); } else { // here id: number console.log(id.toFixed(2)); } } ``` The check `typeof id === "string"` is a **built-in type guard**. TS automatically narrows the type inside each branch. --- ## Main kinds of Type Guards | Kind | Check | Example | | --- | --- | --- | | `typeof` | for primitives | `typeof value === "string"` | | `instanceof` | for classes and constructors | `value instanceof Date` | | `in` | checking whether a property exists | `"prop" in obj` | | A custom `v is Type` function | a custom type guard | `isString(value): value is string` | --- ## 1. A type guard via `typeof` Used to check **primitive types**: `"string"`, `"number"`, `"boolean"`, `"symbol"`, `"undefined"`, `"object"`, `"function"`. ```javascript function process(val: string | number | boolean) { if (typeof val === "string") { // val: string console.log(val.toUpperCase()); } else if (typeof val === "number") { // val: number console.log(val.toFixed(2)); } else { // val: boolean console.log(val ? "true" : "false"); } } ``` --- ## 2. A type guard via `instanceof` Used to check whether an object was created by a specific class or constructor. ```javascript function logDate(value: Date | string) { if (value instanceof Date) { // value: Date console.log(value.toISOString()); } else { // value: string console.log(value.toUpperCase()); } } ``` --- ## 3. A type guard via the `in` operator Checks **whether an object has a specific property**, and TS narrows the type depending on the result. ```javascript type Car = { drive: () => void }; type Boat = { sail: () => void }; function move(vehicle: Car | Boat) { if ("drive" in vehicle) { // vehicle: Car vehicle.drive(); } else { // vehicle: Boat vehicle.sail(); } } ``` --- ## 4. Custom type guards (`v is Type`) You can declare **your own function** that returns a boolean **and tells TypeScript** that if it returns `true`, the argument has a specific type. Syntax: ```javascript function isDog(pet: Animal): pet is Dog { return (pet as Dog).bark !== undefined; } ``` Usage example: ```javascript type Dog = { bark: () => void }; type Cat = { meow: () => void }; function isDog(animal: Dog | Cat): animal is Dog { return (animal as Dog).bark !== undefined; } function makeSound(animal: Dog | Cat) { if (isDog(animal)) { animal.bark(); // animal: Dog } else { animal.meow(); // animal: Cat } } ``` > Here the expression `animal is Dog` tells TS: > "If the function returned true, then animal is definitely a Dog from here on". --- ## Type guards and narrowing Type guards are the main mechanism through which **type narrowing** happens. In effect: > Type guard → triggers narrowing. --- ## An advanced example ```javascript type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function isCircle(s: Shape): s is { kind: "circle"; radius: number } { return s.kind === "circle"; } function area(shape: Shape) { if (isCircle(shape)) { // shape: circle return Math.PI * shape.radius ** 2; } else { // shape: square return shape.side ** 2; } } ``` --- ## Real-world use cases - Validating data after parsing JSON - Checking API responses (runtime type checking) - Filtering arrays by type - Working with union types and discriminated unions - Narrowing when working with `unknown` and `any` --- ### Example: filtering an array ```javascript function isString(value: unknown): value is string { return typeof value === "string"; } const mixed = [1, "a", 2, "b", true]; const strings = mixed.filter(isString); // strings: string[] ``` --- ## Summary | Term | Definition | | --- | --- | | **Type Guard** | A check that helps TypeScript determine the specific type of a value | | **Goal** | Narrowing union or unknown types | | **Kinds** | `typeof`, `instanceof`, `in`, custom (`value is Type`) | | **Main benefit** | Safe access to properties and methods of specific types without casts (`as`) | --- **Put simply:** > A Type Guard is a "guard" that stands in the path of a union type and tells TypeScript: > "Don't worry, I checked, now we know exactly who this is".For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.