6

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?

Celsiuss
  • 895
  • 7
  • 19
Alberto Valero
  • 410
  • 4
  • 14
  • 1
    Does this answer your question? [How do I type an object with known and unknown keys in TypeScript](https://stackoverflow.com/questions/49969390/how-do-i-type-an-object-with-known-and-unknown-keys-in-typescript) – Roberto Zvjerković Jun 23 '21 at 09:15
  • I have tried this: ``` type Attr = { [key: string]: string }; interface Attributes extends Attr { "!!!ExactlyOneOtherStringPropertyNoMoreNoLess!!!": string[]; } ``` But it does not work either. Same error: ``` (property) Attributes["!!!ExactlyOneOtherStringPropertyNoMoreNoLess!!!"]: string[] Property '"!!!ExactlyOneOtherStringPropertyNoMoreNoLess!!!"' of type 'string[]' is not assignable to string index type 'string' ``` – Alberto Valero Jun 23 '21 at 13:20
  • I think tis answer is revelant https://stackoverflow.com/a/61434547/11637098 – Toothgip May 24 '23 at 13:21

1 Answers1

4

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;
};
Luiz Ferraz
  • 1,427
  • 8
  • 13
  • First and second do not kork, I don't know why :( Property 'options' is incompatible with index signature. Type 'string[]' is not assignable to type 'string' – Alberto Valero Jul 01 '21 at 11:30