Alberto Valero
Alberto Valero

Reputation: 440

Typescript object with [key: string]: string | string[]

I have a type defined as follows:

type IColumn = {
  name: string;
  key: string;
  attributes: { [key: string]: string | string[] };
  shortable: boolean;
};

The only field of attributes that can be string[] is called options

So I would like to do something of the type:

type IColumn = {
  name: string;
  key: string;
  attributes: { [key: string]: string ; options: string[] };
  shortable: boolean;
};

To avoid having to specify at each use of attributes whether it is string or string[]. But this does not work.

Is there a way to make it?

Upvotes: 7

Views: 13513

Answers (1)

Luiz Ferraz
Luiz Ferraz

Reputation: 1525

Index signature like that requires that every possible value matches that signature. If you want that as a fallback you have to do an intersection with a in string signature:

type IColumn = {
  name: string;
  key: string;
  attributes: { [key in string]: string }
    & { options: string[] };
  shortable: boolean;
};

Or using the nice aliases in the standard library:

type IColumn = {
  name: string;
  key: string;
  attributes: Record<string, string> & { options: string[] };
  shortable: boolean;
};

If you think you might have this pattern in multiple places you can make a helper type like this:

export type WithDefault<Default, T extends Record<string, any>> = Record<string, Default> & T;

type IColumn = {
  name: string;
  key: string;
  attributes: WithDefault<string, {
    options: string[],
    someFlag: boolean,
  }>;
  shortable: boolean;
};

Upvotes: 3

Related Questions