Suggest an editImprove this articleRefine the answer for “What is a type guard function?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A **type guard function** is a special function that returns a boolean and tells TypeScript that if it returned `true`, its argument has a specific type - through the `value is SomeType` annotation (a type predicate). **Key point:** TypeScript does not execute the function body or verify the logic inside it - it simply trusts the `value is Type` annotation as the developer's promise.Shown above the full answer for quick recall.Answer (EN)Image## What a Type Guard Function is > A **type guard function** is a special function > that returns a boolean **and tells TypeScript** > that if it returned `true`, then its argument has a specific type. Syntax: ```javascript function isSomething(value: unknown): value is SomeType { // check logic } ``` The key part is the return type: `value is SomeType` -> a **type predicate**. --- ## Example 1. A basic custom type guard ```javascript function isString(value: unknown): value is string { return typeof value === "string"; } function print(value: unknown) { if (isString(value)) { // here value: string console.log(value.toUpperCase()); } else { // value is not a string console.log("Not a string"); } } ``` Thanks to `value is string`, TypeScript **understands** that inside `if (isString(value))` the variable's type **has narrowed to** `string`. --- ## Why Type Guard Functions are needed 1. To **extend** TypeScript's type system - teaching it to understand your checks. 2. To **avoid forced casts (**`as`**)**. 3. To **safely work** with `unknown`, `any`, or union types. 4. To **narrow types** inside logical conditions, filters, and higher-order functions. --- ## Example 2. Checking an array ```javascript function isArray(value: unknown): value is any[] { return Array.isArray(value); } function process(value: unknown) { if (isArray(value)) { // value: any[] console.log(value.length); } else { console.log("Not an array"); } } ``` --- ## How this works under the hood A regular function returns `boolean`: ```javascript function check(value: unknown): boolean ``` TypeScript cannot infer a type from this. But a function with a *type predicate* (`value is Type`) tells the compiler: > "If I returned true, treat the variable as now having type `Type`". --- ## Example 3. With a union type ```javascript type Dog = { kind: "dog"; bark: () => void }; type Cat = { kind: "cat"; meow: () => void }; function isDog(animal: Dog | Cat): animal is Dog { return animal.kind === "dog"; } function makeSound(animal: Dog | Cat) { if (isDog(animal)) { animal.bark(); // animal: Dog } else { animal.meow(); // animal: Cat } } ``` This is a typical example of **type guard + narrowing**: the `isDog` function narrows the union type `Dog | Cat` to a specific subtype. --- ## Where it's often used | Scenario | Example | |---|---| | Checking an argument's type | `isString(x)` | | Checking for null/undefined | `isNonNull(x)` | | Checking a discriminant | `isError(response)` | | An instanceof check | `isDate(obj)` | | Filtering an array | `arr.filter(isString)` | --- ## Example 4. Filtering an array with a Type Guard ```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[] ``` TypeScript knows that only `string`s remain after the filter. --- ## Example 5. Checking complex structures ```javascript type User = { id: number; name: string }; function isUser(obj: any): obj is User { return ( typeof obj === "object" && obj !== null && typeof obj.id === "number" && typeof obj.name === "string" ); } const data: unknown = JSON.parse('{"id":1,"name":"Tom"}'); if (isUser(data)) { // data: User console.log(data.name.toUpperCase()); } ``` Without a type guard you would have had to write: ```javascript const user = data as User; // unsafe, may fail at runtime ``` --- ## Example 6. Checking whether a key exists ```javascript function hasProperty<T extends object, K extends PropertyKey>( obj: T, key: K ): obj is T & Record<K, unknown> { return key in obj; } const person = { name: "Alex" }; if (hasProperty(person, "name")) { // person: { name: string } & Record<"name", unknown> console.log(person.name); } ``` --- ## Example 7. Composing several type guards ```javascript function isDefined<T>(value: T | undefined | null): value is T { return value != null; } function isPositive(n: number): boolean { return n > 0; } const arr = [1, null, 2, undefined, -5, 3]; const positive = arr.filter(isDefined).filter(isPositive); // positive: number[] ``` After `isDefined`, TypeScript knows that the array no longer contains `null` or `undefined`. --- ## The difference between a Type Guard Function and a regular function | Regular function | Type Guard Function | |---|---| | Returns `boolean` | Returns `value is Type` | | Does not change the variable's type | Narrows the variable's type | | Does not affect the compiler | Changes how TS perceives the type | | Used as a logical check | Used as *proof of type* | --- ## Example: how TS "thinks" ```javascript if (isUser(obj)) { // TypeScript "believed" the isUser check // obj: User } else { // obj: unknown } ``` TypeScript **does not execute the function**, it simply trusts the `value is Type` annotation - this is the *developer's promise* that the function's logic is indeed correct. --- ## Important notes 1. **TypeScript does not verify that the check inside is correct** - that is the developer's responsibility. ```javascript function isNumber(x: any): x is number { return typeof x === "string"; // TS will believe this, even though it's wrong } ``` 2. **Type guards work only with a function parameter**, not with arbitrary variables. 3. **Generics can be used** to build universal guards. --- ## Summary | Term | Definition | |---|---| | **Type Guard Function** | A function that returns `value is Type` and tells TS that the value has the specified type | | **Purpose** | Narrowing types and safely working with `unknown`, `any`, and union types | | **Main feature** | Affects type analysis, not just execution logic | | **Typical syntax** | `function isUser(obj: any): obj is User { ... }` | | **Main advantage** | Safety, autocomplete, and no `as` | --- **Just remember:** > A Type Guard Function is a "guard" > that tells TypeScript: "I checked it, you can trust me - this is exactly this type".For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.