0

I want to map the below JSON to a Typescript interface.

version & localesMap are mandatory and can occur only once.

And Config types can be of any number, each with unique config name.

{
  "version": 0.1, // <----- Mandatory, and can only occur once
  "localesMap": { // <----- Mandatory, and can only occur once
    "en-US": "en",
    "en-GB": "en"
  },
  "config1": {  // <----- optional, can occur more than once (key can vary)
    "goto": "goto1",
    "next": "next1",
    "options": [
      "a1",
      "a2"
    ]
  },
  "myconfig2": {  // <----- optional, can occur more than once (key can vary)
    "goto": "goto2",
    "next": "next2",
    "options": [
      "b1",
      "b2"
    ]
  },
  // myconfig, serverconfig, clientconfig...
}

I've defined the below interfaces:

export interface Config {
  goto?: string,
  next?: string,
  options?: string[]
}

export interface AllConfigs {
  version: number,
  localesMap: {
    [key: string]: string
  },
  //  <----- I want to have multiple 'Config' types here
}

All the ways I tried are resulting in TS errors. Is there a way to do this? Thanks

TS playground: link

manikanta
  • 8,100
  • 5
  • 59
  • 66
  • 2
    Is [this](https://tsplay.dev/WvYXkm) what you are looking for? – captain-yossarian from Ukraine Dec 17 '21 at 09:13
  • 3
    At least related: [*How to combine known interface properties with a custom index signature?*](https://stackoverflow.com/questions/47592546/how-to-combine-known-interface-properties-with-a-custom-index-signature) But that question seems to allow **any** name for the index properties, whereas this one wants `configX` which is better solved as @captain-yossarian shows above. – T.J. Crowder Dec 17 '21 at 09:16
  • @captain-yossarian - Definitely worth posting as an answer, looks great! Hopefully the OP doesn't have a requirement that they be sequential (1, 2, 3 but not 1, 42, 67). I can't imagine you can do that. – T.J. Crowder Dec 17 '21 at 09:21
  • @captain-yossarian Key can be any string, need not be `config` followed by a number. – manikanta Dec 17 '21 at 09:22
  • @T.J.Crowder Thanks for the help. This solved my issue: `[config: string]: string | Config`. I need to allow `string` because of the `version: string`. Accepted answer clearly says: *You need to make the index signature a union type of all the types that can be contained in the interface* – manikanta Dec 17 '21 at 09:23
  • @T.J.Crowder thank you, but I'm pretty sure it is a duplicate. I just can't find appropriate link :( – captain-yossarian from Ukraine Dec 17 '21 at 09:23
  • @T.J.Crowder Can you please add the solution as an answer so that I can accept yours. Thanks – manikanta Dec 17 '21 at 09:26
  • @manikanta - If that was the solution, we should mark this a duplicate of that other question. Just out of curiousity, what's wrong with captain-yossarian's solution? – T.J. Crowder Dec 17 '21 at 09:26
  • @captain-yossarian - This one's *close*, but... https://stackoverflow.com/questions/65878880/typescript-template-literal-as-interface-key – T.J. Crowder Dec 17 '21 at 09:30
  • captain-yossarian's solution is assuming the config key will always start with `config` and in that case `[config: \`config${number}\`]: Config` works. But in my case, the key can be any string. So, when I specified `[key: string]: Config`, I'll get the same error. So, in my case I had to include all possible value type for a string key index. – manikanta Dec 17 '21 at 09:31
  • @manikanta - Ah! I thought it was always `configX`, that's how it looked in the example prior to the recent edit. – T.J. Crowder Dec 17 '21 at 09:32
  • @T.J.Crowder I think you should post it as an answer – captain-yossarian from Ukraine Dec 17 '21 at 09:33
  • Ah, my bad. I thought comment '_(key can vary)_' will make that clear. But seems like it didn't. I've updated the question to be explicit. – manikanta Dec 17 '21 at 09:34
  • 1
    FWIW, [here's that question's answers applied to the above](https://tsplay.dev/WyO1xN). If you can change the structure, though, I would, separating the configs to their own key (`configs: Config[]` or `configs: Record`, etc.). Happy coding! – T.J. Crowder Dec 17 '21 at 09:43
  • @T.J.Crowder Thanks for the TS Playground link. This is exactly how I have now :) – manikanta Dec 17 '21 at 09:48

0 Answers0