简体   繁体   English

打字稿:对通用对象类型的特定查找类型施加约束

[英]Typescript: Place constraint on specific lookup type of generic object type

Alright so here's the problem.好吧,问题来了。 I have the following type and function definitions:我有以下类型和函数定义:

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>
    }
}

My question is, how would place a particular constraint such that T[propName] is of type P ?我的问题是,如何放置特定约束,使T[propName]的类型为P

I've tried the following:我尝试了以下方法:

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>
    }
}

But this forces ALL properties in T to map to type P .但这会强制T所有属性映射到类型P

Force T to have all properties of T强制 T 具有 T 的所有属性

The problem is lack of relation between P and T .问题是PT之间缺乏关系。 We can solve that but setting the relation.我们可以解决这个问题,但要设置关系。 Consider following code:考虑以下代码:

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> is saying that our type T is an object which all properties are type of P . T extends Record<K, P>是说我们的类型T是一个所有属性都是P类型的对象。 Thanks to that we can do t1[propName] and we know that its type of P .多亏了这一点,我们可以做t1[propName]并且我们知道它的类型P

Force T to have properties of P with other properties强制 T 具有 P 的属性和其他属性

We can achieve that by some additional typing consider:我们可以通过一些额外的输入来实现这一点,考虑:

// 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')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM