为什么只有在使用花括号定义时,TypeScript才允许对象具有多余属性?

时间:2017-07-21 04:21:06

标签: typescript

在定义接口时,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'

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

2 个答案:

答案 0 :(得分: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) {}

它会正常工作。事实上,明确键入变量的唯一原因就是故意捕捉到您遇到的错误。

答案 1 :(得分:0)

原因是因为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的灵活性,但仍确保函数具有在运行时正确处理信息所需的数据。