Suggest an editImprove this articleRefine the answer for “The in operator when checking a union”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)The `in` operator checks **whether the given property exists on an object**, and if it does, TypeScript **narrows the type** to the union variant where **that property is defined**. **Key point:** `in` helps TypeScript "understand" which exact object type is currently in front of it.Shown above the full answer for quick recall.Answer (EN)Image## What the `in` operator does when checking a union type The `in` operator checks **whether the given property exists on an object**, and if it does, TypeScript **narrows the type** to the union variant where **that property is defined**. > In simpler terms: > `in` helps TypeScript "understand" which exact object type is currently in front of it. --- ## Example 1. The classic case ```javascript type User = { name: string }; type Admin = { name: string; permissions: string[] }; function printInfo(person: User | Admin) { if ("permissions" in person) { // Here person: Admin console.log("Permissions:", person.permissions); } else { // Here person: User console.log("User:", person.name); } } ``` TypeScript analyzes the union: - `User` does not contain `permissions` - `Admin` contains `permissions` - so inside the `if`, TS narrows the type to `Admin` --- ## Example 2. Several possible types in a union ```javascript type Circle = { radius: number }; type Rectangle = { width: number; height: number }; type Shape = Circle | Rectangle; function area(shape: Shape) { if ("radius" in shape) { // shape: Circle return Math.PI * shape.radius ** 2; } else { // shape: Rectangle return shape.width * shape.height; } } ``` > TypeScript understands: > if the object has `radius`, then it is a **Circle**, otherwise it is a **Rectangle**. --- ## Example 3. Complex types with several unique properties ```javascript type Cat = { meow: () => void }; type Dog = { bark: () => void }; type Animal = Cat | Dog; function makeSound(animal: Animal) { if ("bark" in animal) { // animal: Dog animal.bark(); } else { // animal: Cat animal.meow(); } } ``` > A great way to tell apart similar types without a discriminant field. --- ## Example 4. Checking nested objects The `in` operator also works with nested objects: ```javascript type Employee = { info: { position: string } }; type Contractor = { company: string }; function describe(person: Employee | Contractor) { if ("info" in person) { console.log("Employee:", person.info.position); } else { console.log("Contractor:", person.company); } } ``` --- ## Important 1. The `in` operator **does not check the value**, only **whether the property exists** on the object. ```javascript const obj = { x: undefined }; console.log("x" in obj); // true (the property exists, even though it is undefined) ``` 2. The check only works with **objects** (not primitives): ```javascript "length" in "hello"; // true "x" in 42; // error: number is not an object ``` --- ## When to use `in` | When | Why | |---|---| | In union types with different sets of properties | Great at telling data shapes apart | | When there is no common discriminant field (`kind`) | An alternative to discriminated unions | | In custom type guard functions | Can be embedded in `return "prop" in obj` | --- ## Example of a custom Type Guard based on `in` ```javascript type User = { name: string }; type Admin = { name: string; permissions: string[] }; function isAdmin(person: User | Admin): person is Admin { return "permissions" in person; } function print(person: User | Admin) { if (isAdmin(person)) { console.log("Admin:", person.permissions); } else { console.log("User:", person.name); } } ``` > Here `return "permissions" in person;` helps TypeScript determine > that the `isAdmin` function guarantees the type `Admin`. --- ## SUMMARY | What `in` does | Checks whether the object has the property | |---|---| | Syntax | `"propertyName" in object` | | Returns | `true` if the property exists | | Typing effect | **Narrows the union type** to the variant where the property exists | | Works with | Objects and classes | | Common use | For distinguishing union type variants (`User | --- ### In short: > The **`in` operator** is a built-in Type Guard > that helps TypeScript determine which type from the union is currently in use, > by checking whether a given property exists on the object.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.