首页 > 解决方案 > 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版本中进行了测试。

我不是以英语为母语的人,希望我能清楚地解释我的困惑。

标签: typescriptgenericstypes

解决方案


错误呢,这是因为keyof Obj可能是"a"or "b"which 具有类型numberor string。在表达式obj[key]中,编译器不知道属性类型,它可能是number或者string也是,所以它不允许这样的赋值。是同样的问题。您可以在此处找到解释,请参阅对索引访问类型的不可靠写入的修复

在泛型函数的情况下K extends keyof ObjK类型可以是"a""b"也可以,但是当您调用fn("a", 2)隐式设置K为的函数时,编译器会从第一个参数"a"推断类型。K所以现在,在调用上下文中key"a"type 和Obj[K]is number,因此分配变得正确。


我只是试图向我的妻子解释不同之处,她不是程序员 :) 我认为这也可能会有所帮助:

常用功能:假设您正在吃蛋糕,但您的眼睛是闭着的。你知道它可能是樱桃蛋糕或香蕉蛋糕。你喜欢它的味道,但你不能说“多么美味的香蕉蛋糕!” 因为你不确定它是不是香蕉蛋糕。

通用功能:在这种情况下,你睁大眼睛,你可以选择你想吃的蛋糕,但你仍然有两个选择:樱桃或香蕉。现在,如果您选择了香蕉蛋糕并品尝了它,您可以说“香蕉蛋糕真好吃!”。


推荐阅读