philo
philo

Reputation: 540

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 ?

Upvotes: 7

Views: 4496

Answers (3)

zyf0330
zyf0330

Reputation: 41


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
}

Upvotes: 1

stackoverflowuser234
stackoverflowuser234

Reputation: 31

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>];

Upvotes: 3

Half
Half

Reputation: 5538

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.

Upvotes: 4

Related Questions