Amin_mmz
Amin_mmz

Reputation: 474

How to specify array of key value pairs for a generic object in Typescript?

I want to create a generic solution for a type safe array of key value pairs

suppose we have a type like this:

type Person = {
  name: string,
  age: number,
}

I want to define KeyValArr type to have a type safe solution for usage below:

const myPersonKV: KeyValArr<Person> = [
  { key: 'name', value: 'john' },
  { key: 'age', value: 22 }
]

The solution I had on my mind was to define KeyValArr as below:

type KeyValArr<T> = {
  key: keyof T,
  value: T[keyof T]
}[]

but the problem with this approach is that the code below does not result in any error:

const tmp: KeyValArr<Person> = [
  { key: age, value: 'wrong type!' }
]

how can I define KeyValArr in a way to have type safety on value based on the defined key?

Upvotes: 1

Views: 3040

Answers (2)

Nadia Chibrikova
Nadia Chibrikova

Reputation: 5036

I'd use something like this:

type Person = {
  name: string,
  age: number,
}

type KeyValArr<T,K=keyof T>= (K extends keyof T ? {key: K, value:T[K]} : never)[]
const myPersonKV: KeyValArr<Person> = [
  { key: 'name', value: 'john' },
  { key: 'age', value: 22 },
  { key: 'age', value: '22 }//error
]

Playground

Upvotes: 2

All you need to do is to define union type of allowed values upfront:

type Person = {
  name: string,
  age: number,
}

type Util<T> = {
  [Prop in keyof T]: {
    key: Prop,
    value: T[Prop]
  }
}

type Values<T> = T[keyof T];

type Result = Values<Util<Person>>

const tmp: Array<Result> = [
  { key: ' age', value: 'wrong type!' }, // error,
  { key: 'name', value: 'wer' } // ok
]

Playground

Here, in my blog, you can find how to create similar data structures but with callbacks

Upvotes: 2

Related Questions