使用TypeScript,有人可以解释为什么下面的两个函数调用会给出不同的类型检查结果吗?
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
//This calls is OK
**printLabel(myObj);**
//But this call is warned with error "size doe snot exist in LabelledValue
**printLabel({ size: 10, label: "Size 10 Object" });**
非常感谢。
答案 0 :(得分:1)
这是TypeScript作者的慎重决定。在对象文字中具有多余属性可能是拼写错误的结果,因此它被诊断为错误。此外,使用代码如问题中的printLabel
的第二次调用,size
属性不会在任何地方使用,因此在对象文字中没有任何意义。
但是,TypeScript采取的立场可能存在错误 这段代码。对象文字得到特殊处理并经历过多 将它们分配给其他变量或传递时的属性检查 他们作为参数。如果对象文字具有任何属性 “目标类型”没有,你会收到错误。
答案 1 :(得分:0)
在第一种情况下,typescript隐式地将{ size: number, label: string }
类型的对象强制转换为LabelledValue
,这样可以正常工作。
在第二种情况下,typescript认为你正在尝试创建LabelledValue
类型的对象,所以它会生气,因为size
不是有效的属性。
如果您将类型分配给myObj
,则在第一种情况下会出现相同的错误,例如
var myObj: LabelledValue = {size: 10, label: "Size 10 Object"}; // causes compiler error
我不知道您要对此做些什么,但一种可能的解决方法是将size
添加为您的界面的可选属性,如下所示:
interface LabelledValue {
label: string;
size?: number;
}
答案 2 :(得分:0)
Typescript允许在编译时无法识别的某些非声音操作是安全的。
printLabel(myObj); // un-sound operation
Quote from Typescript handbook:
TypeScript结构类型系统的基本规则是x 如果y至少具有与x
相同的成员,则与y兼容
此处 obj 与 LabelledValue 的类型兼容,因为 obj 所有成员 LabelledValue 需要(即label: string
)
但是,由于对象文字只能指定已知属性,因此以下内容会产生编译错误:
printLabel({ size: 10, label: "Size 10 Object" }); // ERROR
要更正此错误,只需将对象文字明确地转换为<LabelledValue>
:
printLabel(<LabeledValue>{ size: 10, label: "Size 10 Obect" }); // OK