Reputation: 474
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
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
]
Upvotes: 2
Reputation: 33041
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
]
Here, in my blog, you can find how to create similar data structures but with callbacks
Upvotes: 2