输入“字符串|” boolean' 不能分配给类型 'never'。类型“string”不可分配给类型“never”

Wil*_*lly 5 typescript

interface modal {
    name: string;
    check: boolean;
}

type Key = "name" | "check";

const obj: modal = fn();

function fn():any {
    return {
        name: "hello"
    }
}

class Modal {
    name: string;
    check: boolean;
    constructor() {
        this.name = "";
        this.check = false;
        Object.keys(obj).forEach((key: string) => {
            this[key as keyof modal] = obj[key as keyof modal];
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

我在此处收到错误[key as keyof modal]

错误消息:输入“字符串|” boolean' 不能分配给类型 'never'。类型“string”不可分配给类型“never”。 在此输入图像描述

cap*_*ian 4

Object.keysstring[]无论如何,总是要回来。当然,Array<keyof typeof obj>在这种情况下它会返回是预料之中的,但事实并非如此。请参阅github 上的问题列表

在这种情况下应该做的第一件事是type assertion

(Object.keys(obj) as Array<keyof typeof obj>)
Run Code Online (Sandbox Code Playgroud)

然而,这还没有结束。这里还是有一个错误:

this[key] = obj[key]; // error
Run Code Online (Sandbox Code Playgroud)

一般来说,TS不喜欢突变。请参阅我的文章这个答案。

this[key]和的类型obj[key]string | boolean

请看这段代码:

type Key = "name" | "check";

let _name: Key = 'name'
let _check: Key = 'check'
obj[_name] = obj[_check] // error
Run Code Online (Sandbox Code Playgroud)

上面的代码几乎与你的相同,只是你的突变是在迭代器内部,而我的不是。迭代索引和 的类型之间没有绑定key

参见示例:

type Key = "name" | "check";

let _name: Key = 'name'
let _check: Key = 'check'
obj[_name] = obj[_check] // error
Run Code Online (Sandbox Code Playgroud)

这是正确的行为,因为即使 JS 规范也不能保证第一个keyname。JS 引擎保留以任何顺序退还钥匙的权利。当然,在 99.99% 的情况下你会得到预期的订单,但这并不意味着你有保证。

那么,为什么我们会never在错误消息中出现呢?TypeScript 对预期的键(联合)进行交集,因为获取通用类型更安全。-的交集string & boolean给您never,这就是您收到此错误消息的原因。


我相信在不使用的情况下你能做的最好的事情type assertions就是打电话reduce

(Object.keys(obj) as Array<keyof typeof obj>)
  .forEach((key, index) => {
    if (index === 0) {
      const test = key // keyof modal and not "name"
    }
  })
Run Code Online (Sandbox Code Playgroud)

Playground 值得使用implements modal或大写的modal界面。