3

I'm building an application that access an API that returns an object with many unknown keys, each key represents an id of a user.

Example:

const response = {
  "random id1": {name: "user1"},
  "random id2": {name: "user2"},
  ...
  "random id100": {name: "user100"}
}

I know that if I have just one unknown key I can define using something like:

type MyDefinition = {
  [key: string]: Metadata
}

But how can I define an object with so many different keys?

Felipe César
  • 1,234
  • 2
  • 16
  • 34
  • 3
    `[key: string]` allows for multiple unknown keys though, as long as they're all strings – Samathingamajig Oct 23 '21 at 20:34
  • 2
    What limits the latter to "one key"? You could also use `type MyDefinition = { [key: \`random id${number}\`]: MetaData; }`, but that's just if you want it more precise (and it would still not match perfectly, as it allows generic numbers, e.g. "random id1e4"). – ASDFGerte Oct 23 '21 at 20:34
  • The answers you're getting here seem like they specifically are dealing with keys literally of the form `"random id123"` but I assume that the actual random ids you're talking about don't have any such constraint on them. In which case you should just use an [index signature](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) as @Samathingamajig has suggested (and should probably post as an answer). Index signatures do not restrict to a single key and I'm not sure what gave you that idea; is that something you ran into somewhere? – jcalz Oct 24 '21 at 01:20
  • @Samathingamajig you solved my problem. I didn't know this allows multiple keys. If you post an answer I would be happy to accept it :) – Felipe César Oct 26 '21 at 15:21

3 Answers3

4

[key: string] allows for any amount of unique strings as keys.

type Metadata = {
  name: string
}

type MyDefinition = {
  [key: string]: Metadata
}

const response: MyDefinition = {
  "random id1": {name: "user1"},
  "random id2": {name: "user2"},
  // ...
  "random id100": {name: "user100"},
};

Try it on TypeScript Playground

Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
3

Extending @ASDFGerte comment. You can generate a range of numbers from 0 to 998 in typescript 4.5:


type MAXIMUM_ALLOWED_BOUNDARY = 999

type ComputeRange<
  N extends number,
  Result extends Array<unknown> = [],
  > =
  (Result['length'] extends N
    ? Result
    : ComputeRange<N, [...Result, Result['length']]>
  )

// 0 , 1, 2 ... 998
type NumberRange = ComputeRange<MAXIMUM_ALLOWED_BOUNDARY>[number]

type Name<T extends string> = { name: T }

type CustomResponse = {
  [Prop in NumberRange]: Record<`random id${Prop}`, Name<`id${Prop}`>>
}


Playground

enter image description here

Here and here you can find an explanation of number range.

You have probable noticed that there is a limit you can't cross.

With above approach it will not allow random id1e4.

2

You can use a type defined with a template string like this:

const response: { [key: `random id${number}`]: { name: string }} = {
  "random id1": {name: "user1"},
  "random id2": {name: "user2"},
  "random id100": {name: "user100"}
}

You can see it in action on this TypeScript playground.

Guerric P
  • 30,447
  • 6
  • 48
  • 86