在定义接口时,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'
在声明其类型时,您似乎可以为对象分配任意数量的属性,但由于它们不在类型定义中,因此您无法访问其中的任何属性。这是为什么?
答案 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的灵活性,但仍确保函数具有在运行时正确处理信息所需的数据。