Заставить T иметь все свойства T
Проблема заключается в отсутствии связи между 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
.
Заставляет T иметь свойства 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')