好的,这就是问题所在。我具有以下类型和函数定义:
export type compareFunction<T> = (t1: T, t2: T) => boolean
function createCompareFunctionCreator<P>(customCompare: compareFunction<P>) {
return <
T,
K extends keyof T
>(propName: K) => {
return (t1: T, t2: T) => customCompare(t1[propName], t2[propName]) as compareFunction<P>
}
}
我的问题是,如何放置特定约束以使T[propName]
的类型为P
?
我尝试了以下操作:
function createCompareFunctionCreator<P>(customCompare: compareFunction<P>) {
return <
T extends { [keys in keyof T]: P },
K extends keyof T
>(propName: K) => {
return (t1: T, t2: T) => customCompare(t1[propName], t2[propName]) as compareFunction<P>
}
}
但这会强制T
中的所有属性映射为类型P
。
答案 0 :(得分:2)
问题是P
和T
之间缺乏联系。我们可以解决这个问题,但要设置关系。考虑以下代码:
export type compareFunction<T> = (t1: T, t2: T) => boolean
function createCompareFunctionCreator<P>(customCompare: compareFunction<P>) {
return <
T extends Record<K, P>, // pay attention here
K extends keyof T
>(propName: K) => {
return (t1: T, t2: T) => customCompare(t1[propName], t2[propName])
}
}
T extends Record<K, P>
表示我们的类型T
是一个对象,其所有属性均为P
类型。因此,我们可以执行t1[propName]
,并且知道其类型为P
。
我们可以通过其他一些输入来实现:
// utility type which gives us only keys which values in T1 are T2
type OnlyKeysOfT<T1, T2> = {
[K in keyof T1]: T1[K] extends T2 ? K : never
}[keyof T1]
function createCompareFunctionCreator<P>(customCompare: compareFunction<P>) {
return <
T extends Record<K, P>,
K extends OnlyKeysOfT<T, P> = OnlyKeysOfT<T, P>,
>(propName: K) => {
return (t1: T, t2: T) => customCompare(t1[propName], t2[propName])
}
}
// below only a is correct
createCompareFunctionCreator<string>((a,b) => true)<{a: string, b: number}>('a')