← Back to TypeScript Course | Chapter 5: Type Aliases and Union Types | Lesson 9 of 9

in Operator Guard

The in operator checks whether a property exists on an object. TypeScript can use this check to narrow a union of object types based on properties that distinguish the members.

Basic in Operator Guard

The in operator has the form property in object, and when different object types in a union have different property names, checking for one of those properties lets TypeScript narrow the value to whichever branch of the union actually has it.

Example: Basic in Operator Guard

typescript
type Cat = { meow: () => void };
type Dog = { bark: () => void };
function speak(pet: Cat | Dog) {
  if ("meow" in pet) {
    pet.meow();
  } else {
    pet.bark();
  }
}
speak({ meow: () => console.log("Meow") });

in Operator with Object Properties

The in operator is useful when object types share some properties but each has additional properties the others lack, since checking for the distinguishing property is often simpler than relying on a dedicated discriminant field.

Example: in Operator with Object Properties

typescript
type Circle = { radius: number };
type Square = { side: number };
function area(shape: Circle | Square): number {
  if ("radius" in shape) {
    return 3.14 * shape.radius ** 2;
  }
  return shape.side ** 2;
}
console.log(area({ side: 4 }));

in Operator with Methods

The property checked by in does not have to hold data; it can also be a method name, which is useful for narrowing between interfaces that are shaped like capabilities (for example, checking for a fetchData method) rather than plain data fields.

Example: in Operator with Methods

typescript
type Flyer = { fly: () => void };
type Swimmer = { swim: () => void };
function move(entity: Flyer | Swimmer) {
  if ("fly" in entity) {
    entity.fly();
  } else {
    entity.swim();
  }
}
move({ fly: () => console.log("Flying") });

in Operator with Multiple Union Members

The in operator can be used repeatedly when a union contains several object types, checking one candidate property per branch until the code has narrowed the value down to a single specific shape.

Example: in Operator with Multiple Union Members

typescript
type A = { a: string };
type B = { b: string };
type C = { c: string };
function handle(value: A | B | C) {
  if ("a" in value) console.log("A:", value.a);
  else if ("b" in value) console.log("B:", value.b);
  else console.log("C:", value.c);
}
handle({ c: "hi" });

in Operator with Unknown Values

The in operator can also help narrow unknown values, but the value must first be confirmed to be an object (for example with typeof value === object && value !== null) before TypeScript will allow a property check on it.

Example: in Operator with Unknown Values

typescript
function printName(value: unknown) {
  if (typeof value === "object" && value !== null && "name" in value) {
    console.log((value as { name: string }).name);
  }
}
printName({ name: "Ravi" });
🔒

Chapter Quiz — Complete all 9 topics to unlock

0/9 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.