【问题标题】:Why does TypeScript allow excess properties on objects only when defined with curly braces?为什么 TypeScript 仅在使用花括号定义时才允许对象有多余的属性?
【发布时间】:2018-12-11 07:03:27
【问题描述】:

在定义接口时,TypeScript 文档提到,只要对象采用接口的形状,任何多余的对象属性都是允许的。

一个例子

interface Person {
    name: string
}

function print(somebody: Person) {
    console.log(somebody.name);
}

let obj = { name: "Johnny", additionalProps: true }

print(obj); // this is okay

但这仅适用于函数参数吗?下面我尝试创建一个转换为特定类型的对象,并且仅当我不使用花括号时,添加其他属性才会引发错误。

interface Animal {
    name: string;
}

let myDog = <Animal> { 
    name: "Spot",
    altProperty: "anything" // no error
};

myDog.altProperty = "anything else"; // Property 'altProperty' does not exist on type 'Animal'

似乎您可以在声明对象类型时为其分配任意数量的属性,但您无法访问其中任何一个,因为它们不在类型定义中。这是为什么呢?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    typescript 中的接口仅提供编译时检查,解释对象上可用的成员。

    你的代码在这里:

    let myDog = <Animal> 
    

    是说“我有一些对象,但我只想公开Animal 接口定义的成员”。您已明确告诉编译器在您引用未在Animal 中定义的成员时给您一个错误。

    你可以在创建对象时引用altProperty,因为你还没有给它一个类型。但是,您是否要写:

    let myDog: Animal = { 
        //name: "Spot",
        altProperty: "anything" // no error
    };
    

    尝试将无效对象强制转换为 Animal 时会出错

    现在,您无需将对象强制转换为 Animal 即可使用它。你可以写:

    interface Animal {
        name: string;
    }
    
    let myDog = { 
        name: "Spot",
        altProperty: "anything"
    };
    
    myDog.altProperty = "anything else";
    
    doSomething(myDog);
    function doSomething(object: Animal) {}
    

    而且它会正常工作。实际上,像您所做的那样显式键入变量的唯一原因是故意捕获您遇到的错误。

    【讨论】:

      【解决方案2】:

      原因是因为 TypeScript 的类型系统是基于结构子类型的,我认为可以最好地概括为,如果对象具有该类型的属性,则它对应于该类型。有些人开玩笑说这只是“鸭子打字”(即,如果它像鸭子一样嘎嘎叫,那么它就是鸭子)。

      因此,在您的示例中,它实际上与使用接口声明而不是简单的花括号无关。

      interface Person {
          name: string
      }
      interface PersonPlusMore {
          name: string,
          age: number
      }
      
      function print(somebody: Person) {
          console.log(somebody.name);
      }
      
      let obj : PersonPlusMore = { name: "Johnny", age: 30 }; // <-- notice that we used explicit typing
      
      print(obj); // this is still okay because it has "at least" the properties that your print function requires
      

      通过这种方式,TypeScript 保留了 JavaScript 的灵活性,但仍确保函数具有在运行时正确处理信息所需的数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-07
        • 1970-01-01
        • 1970-01-01
        • 2019-08-03
        • 2014-06-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多