TypeScript 当两个参数引用同一泛型类型时,泛型函数参数丢失类型推理

bnlyeluc  于 2022-10-29  发布在  TypeScript
关注(0)|答案(4)|浏览(138)

{"header":{"type":"auto_translation","ret_code":"NullPointerException","time_cost":1945.0,"request_id":"87f31dbc571e11edabe3bd0c82afb82d"}}

cx6n0qe3

cx6n0qe31#

我不知道你想在这里展示什么缺陷,也不知道为什么要这样写这些定义。看起来你想为f写一些声明,但是遇到了问题,但是没有提供应该允许的内容/不正确的调用

ercv8c1e

ercv8c1e2#

@瑞安·卡瓦诺
简而言之,这很好用

function f<T extends () => Record<string, Function>>(
    props: {
        T: T,
        U: Record<keyof ReturnType<T>, any> /* --- This line --- */
    }
)

但这使得TS丢失了对T和U的所有类型推理。

function f<T extends () => Record<string, Function>>(
    props: {
        T: T,
        U: (param: Record<keyof ReturnType<T>, any>) => void /* --- This line --- */
    }
)

唯一的区别是,在第一个U中是一个Record,而在另一个U中是一个Function。

nzk0hqpo

nzk0hqpo3#

你说“失去所有类型的推论”是什么意思?
例如,该方法可以:

function f<T extends () => Record<string, Function>>(
    props: {
        T: T,
        U: (param: Record<keyof ReturnType<T>, any>) => void /* --- This line --- */
    }
) {

}

function someFunc() { }

f({
    T: () => ({ x: someFunc, y: someFunc }),
    U: (param) => {
        param.x; // strongly-checked, cannot write param.z here
    }
})
wvmv3b1j

wvmv3b1j4#

看起来和语法有关。
使用您刚才展示的工作示例进行演示:

function f<T extends () => Record<string, Function>>(
    props: {
        T: T,
        U: (param: Record<keyof ReturnType<T>, any>) => void
    }
) {

}

function someFunc() { }

f({
    T: () => ({ x() {}, y: someFunc }),  // Changed X here.
    U: (param) => {
        param.z; // no longer strongly-checked, param.z works just fine here.
    }
})

下面的3种语法非常等价,但是当U也出现在类型中并且引用T的返回类型时,TS似乎不能很好地理解最后一种语法。

function someFunc() { }
T: () => ({ x: someFunc, y: someFunc }), // Correct - y and x inferred as keys

T: () => ({ x: () => {}, y: () => {} })  // Correct - y and x inferred as keys

T: () => ({ x() {}, y() {} }),           // Incorrect - type inferred to 'string'

有趣的是,如果你像这样改变U的类型,它可以和T的所有3个变体一起工作。

U: (param: Record<keyof ReturnType<T>, any>) => void 

        /* changed to */

        U: <V extends T>(param: Record<keyof ReturnType<V>, any>) => void

这里是第一个U示例,这里是第二个通用示例

相关问题