typescript - Typescript 编译器永远不会出错:Type 'string | number' 不可分配给类型 'never'。类型“字符串”不可分配给类型“从不”
问题描述
这是我得到的一段代码:
interface Obj {
a: number
b: string
}
const obj: Obj = {
a: 1,
b: 'hi'
}
function fn(key: keyof Obj, value: Obj[keyof Obj]) {
let foo = obj[key]
obj[key] = value
}
fn("a", 2)
所以我想要做的是,我希望函数fn()
能够更新对象obj
属性,这个函数的第一个参数是任何obj
具有(在Obj
接口中定义)的键,第二个参数是你想要赋予它的值钥匙。
但是,打字稿弹出此行中有错误obj[key] = value
,即:
Type 'string | number' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'.(2322)
这是一个屏幕截图:
这里发生了一件奇怪的事情,如果您将鼠标悬停在变量上foo
(即图片中的第 13 行),它会显示:
let foo: string | number
这意味着,obj[key]
的类型是string | number
,但错误说obj[key]
类型是never
。
所以我的第一个问题是:为什么
string | number
类型会神奇地变成 never 类型?有没有什么办法解决这一问题?
然后我得到了另一段代码来解决这个问题:
interface Obj {
a: number
b: string
}
const obj: Obj = {
a: 1,
b: 'hi'
}
function fn<K extends keyof Obj>(key: K, value: Obj[K]) {
obj[key] = value
}
fn("a", 2)
因此我的第二个问题是:为什么要使用
Generics
解决问题以及这里的关键字是什么extends
?
顺便说一句,所有代码都在打字稿3.7.5
版本中进行了测试。
我不是以英语为母语的人,希望我能清楚地解释我的困惑。
解决方案
错误呢,这是因为keyof Obj
可能是"a"
or "b"
which 具有类型number
or string
。在表达式obj[key]
中,编译器不知道属性类型,它可能是number
或者string
也是,所以它不允许这样的赋值。这是同样的问题。您可以在此处找到解释,请参阅对索引访问类型的不可靠写入的修复。
在泛型函数的情况下K extends keyof Obj
,K
类型可以是"a"
或"b"
也可以,但是当您调用fn("a", 2)
隐式设置K
为的函数时,编译器会从第一个参数"a"
推断类型。K
所以现在,在调用上下文中key
有"a"
type 和Obj[K]
is number
,因此分配变得正确。
我只是试图向我的妻子解释不同之处,她不是程序员 :) 我认为这也可能会有所帮助:
常用功能:假设您正在吃蛋糕,但您的眼睛是闭着的。你知道它可能是樱桃蛋糕或香蕉蛋糕。你喜欢它的味道,但你不能说“多么美味的香蕉蛋糕!” 因为你不确定它是不是香蕉蛋糕。
通用功能:在这种情况下,你睁大眼睛,你可以选择你想吃的蛋糕,但你仍然有两个选择:樱桃或香蕉。现在,如果您选择了香蕉蛋糕并品尝了它,您可以说“香蕉蛋糕真好吃!”。
推荐阅读
- jenkins - 如何从rancher 2.0获取kubernete的配置?
- sql-server - 更改 Bool 时 SQL Server 调整计算
- uipath - uipath 编排器中的动态调度
- python - 替换字节数组中的字节以修复编码
- sabre - 如何将 Sabre 预订排入队列(现在预订并在特定时间之前创建 PNR)?
- angular - 使用 Rxjs 或任何东西在 Angular 中监听数据库数据变化
- svn - 如何检查 HEAD 和过去 10 天之间的 svn 日志
- google-cloud-platform - 单租户节点定价
- spring-data - 使用弹簧调度程序时如何在使用沙发底座时锁定文档
- powershell - Powershell copy-item:正在更改文件名