打字稿 - 输入 'string | 数字”不可分配给类型“从不”

Bur*_*ort 7 typescript

我似乎不知道如何解决它。它抛出以下错误:Type 'string | number' is not assignable to type 'never'

这是我的代码。非常感谢任何想法或任何提示。


interface User {
    name: string
    age: number
}

const user: User = {
    name: "someone",
    age: 20
}

const getValue = (key: keyof User) => {
    return user[key]
}

const setValue = (key: keyof User, value: string | number) => {

    let _user: User = Object.assign({}, user);
    return _user[key] = value;  <---- error is thrown here
}
Run Code Online (Sandbox Code Playgroud)

小智 13

您在函数中声明类型的方式会setValue导致 Typescript 正确确定 type 不存在可能的值_user[key]

让我们更详细地探讨这一点。

问题

您的User接口包含两个属性,一个是 type string,另一个是 type number

key您的函数的参数的setValue类型为keyof User

到目前为止一切都很好...

然而,在“编译时”,Typescript 无法确定正在提供哪个键进行查找,因此无法确定哪种特定类型_user[key]

Typescript在编译时知道的,是类型stringnumber. 因此它推断出交集类型string & number

哪一组类型既是字符串数字?

正确 - 没有这样的类型;因此,Typescript 正确推断 的类型_user[key]是类型的空集 - 称为类型never

简单演示


首先,使用 Typescript 提示打开您最喜欢的 IDE,并定义一个具有交集类型的变量:

let a : string & number;
Run Code Online (Sandbox Code Playgroud)

描述性地说,这就是说 的类型是和a的所有可能类型的集合。stringnumber

Typescript 正确地推断出实际上不存在这样的类型,a因此类型为never

VS 代码截图


相反,假设您的User接口具有 type 的两个属性string

interface User {
    name: string
    age: string
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果您传入并仅使用字符串,您的代码将正常工作。

这相当于说 的类型_user[key]是交集类型string & string——当然很简单string

VS代码截图2


解决方案

为了在setValue函数中进行正确的类型推断,您需要提供一个泛型类型,您可以将其用于函数的keyvalue参数setValue

const setValue = <K extends keyof User>(key: K, value: User[K]) => {
  const _user: User = Object.assign({}, user); // Consider also the ES6 spread operator here
  _user[key] = value;
  return _user;
};
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要一个完全通用的setValue函数,独立于特定类型或对象,您的函数签名可能如下

const setValueOnObj = <T, K extends keyof T>(obj: T, key: K, value: T[K]) => [...]
Run Code Online (Sandbox Code Playgroud)


Big*_*iao 5

const setValue = <K extends keyof User>(key: K, value: User[K]) => {\n  let _user: User = Object.assign({}, user);\n  return _user[key] = value;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后你就可以得到完美的类型检查

\n
setValue(\'name\', 18); // \xe2\x9d\x8c\nsetValue(\'name\', \'yes\'); // \xe2\x9c\x85\nsetValue(\'age\', \'18\'); // \xe2\x9d\x8c\nsetValue(\'age\', 18); // \xe2\x9c\x85\nsetValue(\'otherKey\', \'something\'); // \xe2\x9d\x8c\n
Run Code Online (Sandbox Code Playgroud)\n