1
enum InputType {
  Text = 'text',
  Number = 'number'
}

type InputTypeMapping = {
  [InputType.Text]: string,
  [InputType.Number]: number
}

const inputConfig = {
  full_name: {
    label: 'Name',
    type: InputType.Text
  },
  age: {
    label: 'Age',
    type: InputType.Number
  }
}

Based on the configuration above, I will render a form to the browser, and the expected output object from the form submission should be like this:

{
  full_name: '',
  age: 0
}

I want to create the object type for the expected output based on the inputConfig object in the previous snippet. Each key (keyof inputConfig) should mapped to the appropriate input type mapping (typeof InputTypeMapping[inputConfig[key].type]).

I couldn't find a way to create that kind of type. The expected type should be like this ([key in keyof typeof memberInfoKeys] is valid, but the typeof InputTypeMapping[inputConfig[key].type] is invalid, only to give you a picture of what I am expecting)

type FormOutput = {
  [key in keyof typeof memberInfoKeys]: typeof InputTypeMapping[inputConfig[key].type]
}

Is there any possible way to create such type in Typescript?

rahmathd
  • 143
  • 1
  • 10
  • If you change `typeof InputTypeMapping[inputConfig[key].type]` into `typeof InputTypeMapping[inputConfig[key]["type"]` you will have a valid mapped type. But type of property will be a union type of `string | number` – Eldar Oct 10 '20 at 14:50
  • [Playground](https://www.typescriptlang.org/play?ssl=1&ssc=1&pln=36&pc=2#code/KYOwrgtgBAkiAOYAuAVAnvYUDeBYAUFFCsAB5JQC8UA5EmUjQDQFEBykARsAE5W3gI3HjQIBfAgQDGAexABnCnESoMwefwDaAIhLltTKNo5De2gLpQAhhtkKkAbgJI1sdJn4vMMgGawEyO7qmoLC5pL4XljKgWoAslbw8ACWIADm-HiEUJoxqpgAdHpI5gBcUIo8qWks2bkB+cAFJmHlobziEXaKUKkqAMJyPskZ1FlEPmAANlMA+iBWEMDl40RQU1bcU+U0bIvAzKxrUeV5QUUMR2K1RFZpyzhHRBtbOwCC94fZRCf+KuctDrZCT4EERKJQCjUM7xRIpdKaAAKySkAGsADxRXy9BqDEDDNI6O7ACyGbRRbQAPh0FPM4UirjyeIJQU8amxfWQzJG4NcADEZDwIAB5ZAqTJHTSo4BoHFQaVobFMoYjIJlP6xTAJJLVTRYvycpDcwkK8w0tQWelg-DdCikcoCoWipDisZHYnlADMNygkxm8325W0AEcbAATbTiIA) – Eldar Oct 10 '20 at 14:51

1 Answers1

1

The main problem arises due to the fact that we can not get string literal union type from an enum as discussed here.

But you can achieve the same thing by using const as answer in the same question here.

Check this if it works for you

const InputType = {
  Text: "text",
  Number: "number",
} as const;

type InputTypeMapping = {
  [InputType.Text]: string,
  [InputType.Number]: number,
}

const inputConfig = {
  full_name: {
    label: 'Name',
    type: InputType.Text,
  },
  age: {
    label: 'Age',
    type: InputType.Number,
  },
}

type InputConfigType = typeof inputConfig

// type FormType = {
//     full_name: string;
//     age: number;
// }
type FormType = {
  [K in keyof InputConfigType]: InputTypeMapping[InputConfigType[K]['type']]
}



// explanation

// this gives type
// X = "number" | "text" 
// when `InputType` is a const
// and gives back `InputType` when `InputType` is an enum
type X = (typeof InputType)[keyof typeof InputType]

// to use the InputType as enum in a function or variable
type InputTypeKeys = (typeof InputType)[keyof typeof InputType]

let variable: InputTypeKeys = InputType.Number

function func(_a: InputTypeKeys) {
  // ...
}

func(InputType.Number)

Playground

More on const assertions

Shivam Singla
  • 2,117
  • 1
  • 10
  • 22