'Typescript , How to infer type from another property value?

For example, I have an interface with properties: key and value, I want to infer value type by the key.

interface Obj { a: number; b: string }

interface Param<K extends keyof Obj> {
  key: K
  value: Obj[K] // I want to infer this type
}

const p: Param<keyof Obj> = {
  key: 'a',
  value: '', // typescript can't infer this type, expect number
}

How can I do that ?



Solution 1:[1]

Obj[K] means a value that can be gotten by indexing Obj by any of the values in K, not just the one key is.

So, to use this structure, you need to specify which key is used more closely:

interface Obj { a: number; b: string }

interface Param<K extends keyof Obj> {
  key: K
  value: Obj[K]
}

const p: Param<'a'> = { // changed line
  key: 'a',
  value: '', // error
}

There's no way to infer the generic parameter, sadly.


If you already know what's in Obj, there may be a better way to do this.

interface AParam {
    key: 'a'
    value: number
}

interface BParam {
    key: 'b'
    value: string
}

type Param = AParam | BParam;

const p: Param = {
  key: 'a',
  value: '', // error
}

This is the only approach that will work if you need the variable p to be able to hold either key, but still have the value be the correct type.

Solution 2:[2]

You can reach this goal with the help of mapped types.

type ParamHelper<T> = { [K in keyof T]: { key: K; value: T[K] } };
type Param<T> = ParamHelper<T>[keyof ParamHelper<T>];

Solution 3:[3]


type param<o> = {
    [k in keyof o]: {
        key: k,
        value: o[k]
    }
}[keyof o];
const o = {a:1, b:2} as const
const a: param<typeof o> ={
    key:'a',
    value:1
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Half
Solution 2 stackoverflowuser234
Solution 3 zyf0330