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

时间:2020-01-13 14:01:11

标签: typescript generics functional-programming constraints mapped-types

好的,这就是问题所在。我具有以下类型和函数定义:

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

1 个答案:

答案 0 :(得分:2)

强制T具有T的所有属性

问题是PT之间缺乏联系。我们可以解决这个问题,但要设置关系。考虑以下代码:

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