The in and instanceof Operators

Narrow object unions by asking which properties exist or which class an object came from.

When a union is made of object shapes rather than primitives, typeof is not enough β€” everything is just "object". Two operators pick up the slack.

The in operator

in checks whether a property exists, and TypeScript narrows to the members that have it:

type Dog = { bark: () => void };
type Cat = { meow: () => void };

function speak(pet: Dog | Cat) {
  if ("bark" in pet) pet.bark(); // pet: Dog
  else pet.meow();               // pet: Cat
}

The instanceof operator

instanceof asks "was this built by that constructor?" β€” perfect for real classes and built-ins like Date, Error, or Map.

Reach for in with plain object shapes and interfaces; reach for instanceof when actual class instances are involved. Both are runtime checks, so unlike a type assertion they genuinely protect you at execution time.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • An event handler uses the in operator to check whether the event object has a key property before treating it as a keyboard event.
  • An error boundary checks instanceof Error before accessing the message property on an unknown thrown value.
  • A plugin system uses the in operator to detect which optional methods a plugin object provides before calling them.

More examples

in operator narrows object union

The in operator checks for the presence of a property and TypeScript narrows the union to whichever variant has that property.

Example Β· ts
type Circle = { radius: number };
type Square = { side: number };

function area(shape: Circle | Square): number {
  if ('radius' in shape) {
    return Math.PI * shape.radius ** 2; // shape is Circle
  }
  return shape.side ** 2;              // shape is Square
}

instanceof narrows class types

Chains instanceof from most specific to most general so each branch accesses the right properties.

Example Β· ts
class ApiError extends Error {
  constructor(public status: number, message: string) {
    super(message);
  }
}

function handleError(err: unknown): string {
  if (err instanceof ApiError) return `HTTP ${err.status}: ${err.message}`;
  if (err instanceof Error)    return err.message;
  return 'Unknown error';
}

Combining in and instanceof

Uses instanceof for a concrete class and the in operator for a structural duck-type check in the same function.

Example Β· ts
interface Flyable { fly(): void; }

class Bird implements Flyable {
  fly(): void { console.log('flap'); }
  sing(): void { console.log('tweet'); }
}

function act(obj: object): void {
  if (obj instanceof Bird) {
    obj.sing();
  } else if ('fly' in obj) {
    (obj as Flyable).fly();
  }
}

Discussion

  • Be the first to comment on this lesson.
The in and instanceof Operators β€” TypeScript | SoundsCode