代码之家  ›  专栏  ›  技术社区  ›  apflieger

如何在Typescript中键入检查排列运算符?

  •  0
  • apflieger  · 技术社区  · 6 年前

    有没有办法让它不被编译?(因为它有…)

    const bar: { a: string } = {
        a: '',
        ...{b: ''}
    }
    
    0 回复  |  直到 6 年前
        1
  •  0
  •   William Lewis    6 年前

    我震惊地发现,这通过了打字检查!

    在闲逛了一会儿之后,我对为什么会发生这种情况有了强烈的预感,但我还没有找到任何官方词汇来支持它。 因此,这不是一个答案,而是一个太长而无法发表评论的对话起点。 就这么说吧,把接下来发生的事放在心上。

    我怀疑TypeScript的“归属”/“注释”机制允许基于子类型进行一些调整。 具体来说,当我们写:

    const foo: Foo = bar;
    

    只要 bar 的类型是a 亚型 属于 Foo ,这似乎以优异的成绩通过了检查。 下面是一个具体的例子:

    class Foo {
      public a: string;
    }
    
    // `Bar` is a subtype of `Foo`
    class Bar extends Foo {
      public b: string;
    }
    
    const foo: Foo = new Bar();
    //         ^^^       ^^^ This is just fine!
    

    此外,由于TypeScript的子类型化概念是“结构性的”,以下内容也是完全可以接受的:

    class Foo {
      a: string;
    }
    
    // `Quux` is structurally the same as (and therefore a subtype of) `Foo`
    class Quux {
      a: string;
    }
    
    const foo: Foo = new Quux();
    

    考虑到这个[理论],你的例子被检查者接受,因为 { a: string; b: string } 是 { a: string } .

    总之, 如果 这是正确的,我认为没有办法诱使类型检查器拒绝您的示例。

    编辑 当前位置这不是完整的故事。 正如@apflieger所指出的,这个理论无法解释原因

    const foo: { a: string } = {
      a: 'test',
      b: 'test',
    };
    

    被拒绝。 似乎传播在这里至关重要。

    可能是那种

    {
      a: 'test',
      ...{ b: 'test' }
    }
    

    被推断为 { a: string } & { b: string } ,而在前一种情况下,推断为 {a:string;b:string} .