7

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?

3
  • 1
    Does this answer your question? How do I type an object with known and unknown keys in TypeScript Commented Jun 23, 2021 at 9: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' ``` Commented Jun 23, 2021 at 13:20
  • I think tis answer is revelant stackoverflow.com/a/61434547/11637098 Commented May 24, 2023 at 13:21

1 Answer 1

3

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;
};
Sign up to request clarification or add additional context in comments.

2 Comments

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'
None of this works : ts type Inputs = WithDefault<number | null, { timeserie: [string, number][] }> ``` const timeserie: [string, number][] = [ [faker.date.recent().toISOString(), faker.number.int()], [faker.date.recent().toISOString(), faker.number.int()], [faker.date.recent().toISOString(), faker.number.int()], ]; const inputs: Inputs = { timeserie, A : null, }; ``` Error TS2345

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.