Satsaa
Satsaa

Reputation: 13

Infer type of key based on key that is present in object

I have a type that is used inside an array of inputs. I need type of Input.default to be inferred from the value of Input.key, so that it extends value of T[key]. I'm using typescript 5.0.4

type Input<T, T2 extends key of T> = {
    key: T2
    default: T[key] // type is inferred from value of key
}

E.g. if T = { foo: string, bar: boolean } and key = 'bar', default must be type of boolean. My needs:

var biz: Input<{ foo: string, bar: boolean }>[]

biz = [{
  key: "foo",
  default: "example"
},{
  key: "bar",
  default: true // No eror
},{
  key: "bar",
  default: "not boolean" // Errors
}]

As biz is an array, using typeparameters manually is not possible:

var biz: Input<{ foo: string, bar: boolean }, "bar">[] // Added "bar" as key

biz = [{
  key: "foo",
  default: "example" // Unwanted error. Type is based on T['bar'] not T['foo']
},{
  key: "bar",
  default: true // No eror
},{
  key: "bar",
  default: "not boolean" // Errors
}]

Upvotes: 1

Views: 99

Answers (1)

COnsider this example:

type Shape = { foo: string, bar: boolean }

type Values<T> = T[keyof T]

type DataList<T> = Values<{
  [Prop in keyof T]: {
    key: Prop,
    default: T[Prop]
  }
}>[]

type Result = DataList<Shape>


const biz: DataList<Shape> = [{
  key: "foo",
  default: "example" // Unwanted error. Type is based on T['bar'] not T['foo']
}, {
  key: "bar",
  default: true // No eror
}, {
  key: "bar",
  default: "not boolean" // Errors
}]

Playground

You need to iterate through Shape's keys and create new mapped type where key is a name of a key and default is a type. See this:

[Prop in keyof T]: {
    key: Prop,
    default: T[Prop]
  }

Then you need to wrap it into Values because you are interested in object values.

Just try to remove Values wrapper and check what you have

Upvotes: 0

Related Questions