温馨提示:本文翻译自stackoverflow.com,查看原文请点击:generics - Typescript compiler never Error: Type 'string | number' is not assignable to type 'never'. Type 'str
generics types typescript

generics - Typescript编译器从不错误:键入'string |

发布于 2020-03-27 16:14:20

这是我得到的一段代码:

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

which means, obj[key]'s type is string | number, but the error says obj[key] type is never.

so my first question is: How come a string | number type magically becomes a never type? Is there any way to fix this?

Then i got another piece of code which solves this problem:

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)

Therefore my second question would be: why using Generics solve the problem and what the hack is the keyword extends here?

BTW, all the code are tested in typescript 3.7.5 version.

I am not a native English speaker, hope i explained my confusion clearly.

查看更多

查看更多

提问者
Limboer
被浏览
118
Valeriy Katkov 2020-01-31 20:21

该怎么办,这是因为keyof Obj可能是"a""b"具有类型numberstring在表达式obj[key]的编译器不知道的属性类型,它可能number还是string一样,所以它不允许这样的分配。是同样的问题。您可以在此处找到解释,请参阅针对索引访问类型的不正确写入的修复

在通用功能的情况下,K extends keyof Obj意味着K类型可以是"a""b"为好,但是当你调用函数fn("a", 2)你隐式设置K"a",编译器推断K从第一个参数类型。所以,现在,里面的呼叫内容key"a"型且Obj[K]number,因此分配变得正确。


我只是想向我的妻子(不是程序员)解释这种区别:)我认为这可能也有帮助:

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

通用功能:在这种情况下,您可以睁开眼睛,可以选择要吃的蛋糕,但仍然有两种选择:樱桃或香蕉。现在,如果您选择并品尝了香蕉蛋糕,则可以说“多么美味的香蕉蛋糕!”。