Home > database >  Typescript array of union type - identify type by structure
Typescript array of union type - identify type by structure

Time:07-31

I have a union of two different types, and an array of this union type.
I want to get an error when I try to pass a combination that doesn't exist on any of the interfaces.

interface IMenuItem {
  title: string;
  theme: 'primary' | 'secondary';
}

interface IMenuDivider {
  isDivider: boolean;
  margin?: number;
}

type TItem = IMenuItem | IMenuDivider;

const items: TItem[] = [
  {
    title: 'item title',
    isDivider: true // doesn't error
  }
]

I'd expect this example to trigger an error since this combination isn't defined in any of the interfaces composing the union.

How should I type my TItem to achieve this?

Thanks!

CodePudding user response:

You might want to check your local TS configuration since the provided example throws a type-check error as expected as shown in this repl.

CodePudding user response:

Ok I figured it out. Apparently for this to work they need to share a property to discriminate by.
Not sure 100% why, but adding the type attribute works:

interface IMenuItem {
  type: 'item';
  title: string;
  theme: 'primary' | 'secondary';
}

interface IMenuDivider {
  type: 'divider';
  isDivider: boolean;
  margin?: number;
}

type TItem = IMenuItem | IMenuDivider;

const items: TItem[] = [
  {
    type: 'item',
    title: 'item title',
    isDivider: true // Error: Object literal may only specify known properties, and 'isDivider' does not exist in type 'IMenuItem'.
  }
]

PS - I can guess why. Without the type attribute, typescript can't really know which interface I was aiming for, so it can't tell me which property is wrong.

  • Related