为什么打字稿不能正确推断 T[K] 与 <T extends Person, K extends keyof T> generic?

ent*_*one 7 typescript reactjs typescript-generics react-hooks react-typescript

我创建了一个 React 钩子:

\n
interface Person {\n    name: string\n    age: number\n}\n\nexport const usePerson = function <T extends Person, K extends keyof T>(): (property: K, setter: (value: T[K]) => T[K]) => void {\n\n    const setPersonProperty = (property: K, setter: (value: T[K]) => T[K]): void => {\n        console.log(property, setter)\n    }\n\n    setPersonProperty(\'name\', (x) => x)\n\n    return setPersonProperty;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我已经从打字稿文档中看到了该模式<T, K extends keyof T>,但我无法在我的示例中正确使用它。

\n

更具体地说,打字稿在线抱怨

\n
setPersonProperty(\'name\', (x) => x)\n
Run Code Online (Sandbox Code Playgroud)\n

虽然当我开始输入setPersonProperty(\'n /* IDE autocompletes name */但抱怨参数时\'name\',我收到以下错误:

\n
Argument of type \'string\' is not assignable to parameter of type \'K\'. \xc2\xa0\xc2\xa0\'string\' is assignable to the constraint of type \'K\', but \'K\' could be instantiated with a different subtype of constraint \'string | number | symbol\'.\n
Run Code Online (Sandbox Code Playgroud)\n

我还发布了来自 IDE 的图像。我正在使用打字稿 4+。

\n

在此输入图像描述

\n

我在这里做错了什么?

\n

jmk*_*jmk 4

我打赌这就是你想要达到的结果

type Person = {
    name: string,
    age: number
};

export const usePerson = function <T extends Person>() {
    const setPersonProperty = <K extends keyof T> (property: K, setter: (value: T[K]) => T[K]): void => {
        console.log(property, setter)
    }

    setPersonProperty("name", (x) => x)

    return setPersonProperty;
}

 const setPerson = usePerson<Person>()

 setPerson("name", (name) => name)

Run Code Online (Sandbox Code Playgroud)

T基本上,在您提供的代码中,调用此 usePerson 挂钩和K( )时有两种通用类型<T extends Person, K extends keyof T>

假设有人会用 来调用这个函数usePerson<Person, "age">()。typescript 会做什么,它将替换我们的usePersonto beT = Person中的类型,K = "age"

现在您出现了不匹配,因为setPersonProperty第一个参数的类型为 K(“年龄”),参数“名称”不可分配 - 您看到的错误。