【问题标题】:Type 'string | number' is not assignable to type 'never' in switch statement [duplicate]键入'字符串 | number' 不能分配给 switch 语句中的类型'never' [重复]
【发布时间】:2021-08-17 17:03:59
【问题描述】:

我有一个描述来自 BE 的数据结构的接口,并且一个类具有将该 BE 数据结构转换为我们的 FE 数据结构的方法,反之亦然,但在该打字稿期间抛出 Type 'string | number' is not assignable to type 'never'. Type 'string' is not assignable to type 'never' 错误。我该如何解决,为什么会这样?

interface BEStructure {
  a?: string;
  b?: number;
  ...
}

class FEStructure {
  a: string = null;
  b: number = null;
  ...

  static convertToBE(fe: Partial<FEStructure>): BEStructure  {
    const be: BEStructure = {};

    Object.keys(fe).forEach(key => {
      switch (key) {
        case 'a':
        case 'b': 
          // My others logic
          // ERROR HERE
          be[key] = fe[key];
          break;
      default:
          be[key] = fe[key];
      }
    });

    return be;
  }
}

我创建了a reproduce here

【问题讨论】:

  • 您在 DB 中有一个名为 never 的字段吗? never的类型是什么?
  • @balderman never 是 TypeScript 类型。尚不确定为什么它会隐式发生在这里...
  • 其他"...is not assignable to type 'never'" 问题都没有帮助吗?
  • 发生 TS 错误是因为 switch case 同时适用于 a 和 b,从而创建了一个不可能的类型条件,因为它不能同时是字符串和数字。如果将两者分开,则不会出错。
  • @Rich N fe[key] 是字符串 OR 数字,但 be[key] 需要字符串 AND 数字,因为这是分配给可能需要任一类型的属性的唯一安全方法。这只是一个 TS 错误,而不是实际的运行时问题,因此可以使用 as 断言绕过它。这是编译器的限制,它不明白 be[key] 需要的类型与 fe[key] 的类型相同。

标签: typescript


【解决方案1】:

在这种情况下,TypeScript 分配似乎不够聪明,无法自行进行案例分析。在语句be[key] = fe[key] 中,右侧的类型为string | number,而左侧可通过类型string &amp; number 赋值,其计算结果为never,即永远不能赋值。

这是一个解决方案,它定义了一个正确类型的 assign 泛型函数:

interface BEStructure {
  a?: string;
  b?: number;
}

function assign<T, Key extends keyof T>(obj: T, key: Key, value: T[Key]): void {
  obj[key] = value;
}

class FEStructure {
  a?: string;
  b?: number;

  static convertToBE(fe: FEStructure): BEStructure  {
    const be: BEStructure = {};

    Object.keys(fe).forEach(key => {
      switch (key) {
        case 'a':
        case 'b': 
          //be[key] = fe[key];
          assign(be, key, fe[key])
          break;
      }
    });

    return be;
  }
}

Playground link

【讨论】:

    【解决方案2】:

    请提供可重现的示例。我无法重现您的错误。

    我认为 @Linda Paiste 是对的

    我敢打赌,这是因为 be[key] = fe[key]; 突变。

    Official explanation

    当索引访问 T[K] 发生在类型关系的源端时,它会解析为由 T[K] 选择的属性的联合类型,但是当它发生在类型关系的目标端时类型关系,它现在解析为由 T[K] 选择的属性的交集类型。以前,目标端也会解析为联合类型,这是不合理的。

    根据官方解释 be[key]be[key] = fe[key]; 解析为be['a' &amp; 'b'] 解析为be[never] 触发错误:Type 'string' is not assignable to type 'never'。因为'a' &amp; 'b'的交集给never

    查看这些答案:

    Assigning properties in an object by iterating through its keys,

    How to selectively assign from one Partial to another in typescript,

    Why can I index by string to get a property value but not to set it?,

    TypeScript: Why can't I assign a valid field of an object with type { a: "a", b: "b" }

    My article 专门用于 TS 突变。

    【讨论】:

    • 我在我的问题中添加了一个重现
    • @captain-yossarian 如果将问题中的原始代码粘贴到名为 index.ts 的文本文件中,取出两组“...”(最好注释掉),并做tsc index.ts 你得到错误。我想你一定是做错了?
    • @RichN 我更新了
    猜你喜欢
    • 2022-12-06
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 2021-04-15
    • 2021-07-02
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多