Home > other >  Defining multiple mapped types in typescript?
Defining multiple mapped types in typescript?

Time:03-26

Say I have the following typescript code:

type fruit = "apple" | "banana" | "pear"
type color = "red" | "yellow" | "green"

And I want to create a type that has a numeric property for each fruit and a boolean property for each color, something like

type FruitsAndColors = {
  [key in fruit]: number;
  [key in color]: boolean
}

Unfortunately, this errors with the message "A mapped type may not declare properties or methods", yet it compiles fine. What's actually happening here?

I can get around this with something like

type FruitsAndColors = {
  [key in fruit]: number;
} & {
  [key in color]: boolean
}

But I'd like to know what the actual issue is.

CodePudding user response:

It's not "vscode's typescript extension," it's TypeScript. It doesn't let you do two mappings in a single type construct. It's just the syntax of the construct doesn't allow it.

Instead, you do what you showed:

type FruitsAndColors = {
    [key in fruit]: number;
} & {
    [key in color]: boolean
};

Note, though, that that type requires all six properties to be present in the object. Maybe that's what you want, but if not, add ? after the mapped keys (or wrap the entire thing in Partial<>):

type FruitsAndColors = {
    [key in fruit]?: number;
} & {
    [key in color]?: boolean
};
// Or
type FruitsAndColors = Partial<{
    [key in fruit]: number;
} & {
    [key in color]: boolean
}>;

Playground for the above

CodePudding user response:

Typescript syntax for mapped types doesn't allow multiple mappings. There are two ways you can achieve what you want:

  1. You can use a type union, like the one in your question.
  2. You can also use Record<Fruit, number> & Record<Color, boolean>.

As mentioned in the other answer, note that this will make all properties required, so wrap it all in Partial if that's not what you want.

Playground

Also note that types should start with a capital letter. This is a TS convention that helps with syntax highlighting.

CodePudding user response:

You can also use conditional types:

type FruitsAndColors = Partial<{
  [Key in (Fruit | Color)]: Key extends Fruit ? number : Key extends Color ? boolean : never;
}>

Playground

  • Related