【问题标题】:Type declaration works for object literal, but not for class implementation类型声明适用于对象文字,但不适用于类实现
【发布时间】:2023-03-29 04:23:01
【问题描述】:

我想要一个类型来表示一个坐标。我应用于接口的类型适用于对象,但不适用于类。

type ICoord = [number, number]

type MyInterface = {
    a: ICoord
}

var obj: MyInterface = { // works
    a: [0, 0]
}

class C implements MyInterface { // gets below compilation error
    a = [0, 0]
}

Property 'a' in type 'C' is not assignable to the same property in base type 'MyInterface'. Type 'number[]' is missing the following properties from type '[number, number]': 0, 1

为什么我不能将[0, 0] 分配给a

[TypeScript Playground]

【问题讨论】:

    标签: javascript typescript types


    【解决方案1】:

    a 的类型被推断为number[],它不能分配给元组[number, number]。将a 的类型显式定义为ICoord 似乎可行:

    type ICoord = [number, number];
    
    type MyInterface = {
      a: ICoord;
    }
    
    class C implements MyInterface {
      a: ICoord = [0, 0];
    }
    

    TypeScript Playground

    【讨论】:

    • 虽然是真的,但我确信 OP 想知道为什么在对象字面量中正确处理了推理,而不是在类中。
    • 我需要在两个地方指出a 应该是ICoord 类型,这似乎很奇怪/多余。
    【解决方案2】:

    这与上下文类型有关。

    Typescript 使用表达式的预期类型(在这种情况下为MyInterface)来更好地推断对象字面量(也包括函数参数)。这就是为什么分配对象字面量效果很好并且数组字面量被键入为元组类型的原因。

    对于类,情况有些不同。 implements 子句仅用于检查类在独立类型化之后是否正确实现了接口。 implements 关键字不会为任何类成员创建任何上下文类型。这也是您必须指定函数参数类型的原因,即使它们从接口或基类中显而易见。

    【讨论】:

    • 那么正确的输入方法是什么,这样类就不会出现这个错误。 Skovy 的解决方案似乎是多余的。如果我只需要再次告诉班级a 的数据类型是什么,为什么还要使用接口。
    • 要求此功能的相关 GitHub 问题:microsoft/TypeScript#1373,由于实施它的主要尝试 microsoft/TypeScript#6118 并不顺利(请参阅 comment)而关闭,因为不会修复/跨度>
    • @1252748 正确的做法是再次指定类型。 implements 仅用作对类的检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    相关资源
    最近更新 更多