I want to add a function signature on a typescript interface which one of its parameters will have a type based on the declared key's value.
I've tried the approach bellow but it doesn't work, as the value
's type is every possible type from T
. Instead, I want the value of the declared key
so if key "num" is a number, I want the "value" parameter in function to be a number
type RowType = Record<string, any>
interface Row<T = RowType, K extends keyof T = keyof T> {
key: K
render: (value: T[K], row: T) => any
}
interface DumpRecord = {
arr: string[],
num: number,
str: string
}
let row: Row<DumpRecord> = {
key: 'arr',
render: (value, row) => ... // value should be array, row should be DumpRecord
}
// or
let row: Row<DumpRecord> = {
key: 'num',
render: (value, row) => ... // value should be number
}
CodePudding user response:
You need to use discriminated unions here:
type RowType = Record<string, any>
interface Row<T = RowType, K extends keyof T = keyof T> {
key: K
render: (value: T[K], row: T) => any
}
interface DumpRecord {
arr: string[],
num: number,
str: string
}
type Values<T> = T[keyof T]
type Union = Values<{
[Prop in keyof DumpRecord]: Row<DumpRecord, Prop>
}>
const one: Union = {
key: 'arr',
render: (value, row) => {
value // string[]
}
}
const two: Union = {
key: 'num',
render: (value, row) => {
value // number
}
}
You can find more examples in this question and my article