TypeScript one or the other

Sometimes we run into some code where we need to type a value as either one or the other. In this blog post, we will see how we can achieve this by leveraging TypeScript’s never type.

Let’s use shapes as an example. A shape can have a color, no matter what specific shape it is, but not every shape can have a radius or a side length. We could type it like this:

interface ShapeBase {
  color: string;
}

interface Square extends ShapeBase {
  sideLength: number;
}

interface Circle extends ShapeBase {
  radius: number;
};

type Shape = Square | Circle;

The problem with this type definition is, that an object of type Shape can have a color, side length and a radius without causing an error.

const myShape: Shape = {
  color: 'red',
  sideLength: 123,
  radius: 987
}

How can we achieve that this object can either have a side length OR a radius, but not both?

For this to work, we have to leverage TypeScript’s never type. This type tells Typescript that this property should never exist and therefore results in an error. If you want to read more about never, check out the TypeScript docs. We need to set both properties on both types and mark the unwanted property as optional and type it as never.

interface Square extends ShapeBase {
  sideLength: number;
  radius?: never;
}

interface Circle extends ShapeBase {
  radius: number;
  sideLength?: never
};

type Shape = Square | Circle;

If we try to create an object of Type Shape with a radius and sideLength property, TypeScript now tells us that an error occurred:

As long as we only set one property, either radius or sideLength TypeScript won’t complain anymore.

Thank you,
Tim

Leave a Comment

Your email address will not be published. Required fields are marked *