Alexandra Lim | Front End DeveloperSkip to content
Alexandra Lim

Narrowing types using the in operator in TypeScript

TypeScript2 min read

As part of Fullscript's design systems team, our most recent project has been implementing our new design tokens by changing all of the existing colour values in our component library to use our new light theme tokens. Some of the components in the component library are typed to a set of colour profiles to add a range of colours.

I recently ran into a typing issue where TypeScript was throwing an error as the profile token I used did not exist for all of the colour profiles typed. This was the kind of error I kept getting (names changed for context and easier explanation):

Property 'lettuce' does not exist on type 'Lunch'. 
  Property 'lettuce' does not exist on type 'Steak'.

Let's go back a bit. The type Lunch is a union type, or a type made up of multiple types. Lunch looks something like this:

type Burger = {
  beef: Boolean,
  bun: Boolean,
  ketchup: Boolean,
  mustard: Boolean,
  lettuce: Boolean,
  pickles: Boolean,
};

type Steak = {
  beef: Boolean,
  butter: Boolean,
  garlic: Boolean,
  fries: Boolean,
};

type Lunch = Burger | Steak;

I really want to access the lettuce property in Lunch, but because lettuce is non-existent in the type Steak, I can't access lettuce if I've typed a variable to Lunch since it doesn't exist in both Burger and Steak.

It turns out I can use JavaScript's in operator to remove this TypeScript error and help me access the lettuce property, even though it only exists in one of the types defined in Lunch. The in operator returns true only if the property exists in the object specified or the prototype chain.

Accessing lettuce this way no longer throws an error:

const whatsForLunch = (meal: Lunch) => {
  if ("lettuce" in meal) return meal.lettuce;

  return meal.beef;
}

And that's it! You can read more about how narrowing in TypeScript in the official docs.


If you have any questions or notice an error in this post, drop me a line at [email protected].