为什么空接口不要求对象为空?
interface A {};
const a: A = {a: 1};
console.log(a);
是有效代码,将输出{ a: 1 }
。
我认为添加可选属性应该可以正常工作,但是
interface A {};
interface B extends A {
b?: any;
}
const a: B = {a: 1};
console.log(a);
以错误Type '{ a: number; }' is not assignable to type 'B'
结束。
a
。非空接口定义了哪个对象可以和必须具有。
空接口的行为类似于any
。
是否有解释为什么空接口的行为如下?这是故意还是只是一个错误?
答案 0 :(得分:6)
此行为是故意的。
当目标是空对象类型时,不执行多余属性检查,因为很少只允许空对象。
实际上,你可以将{a: 1}
分配给B,其他答案大多是错误的。
你偶然发现了TypeScript中另一个有点令人困惑的怪癖,即你不能直接将对象文字分配给一个类型,其中对象文字包含除了类型中指定的属性之外的其他属性。 / p>
但是,您可以将对象的任何现有实例分配给类型,只要它符合类型即可。
例如:
interface Animal {
LegCount: number;
}
let dog: Animal = { LegCount: 4, Fur: "Brown" }; // Nope
var myCat = { LegCount: 4, Fur: "Black" };
let theCat: Animal = myCat; // OK
如果您的类型为空,则忽略此约束。
来自Typescript团队的原始答案可在GitHub上找到。
答案 1 :(得分:2)
好的,有趣的问题。
测试案例1:
interface A {};
interface B extends A {
b?: any;
}
const a: A = {a: 1};
console.log(a);
它传递,因为A是一个空的界面,无论你在里面愚蠢的东西都会返回。就像class Object
测试案例2:
interface A {};
interface B extends A {
b?: any;
}
const a: A = {b: 1};
console.log(a);
刚刚将值a
更改为b
只是为了证明第一个测试用例。它过去了。
测试案例3:
interface A {};
interface B extends A {
b?: any;
}
const a: B = {a: 1};
console.log(a);
失败,因为在A
或B
接口内没有名为a
的道具
测试案例4:
interface A {};
interface B extends A {
b?: any;
}
const a: B = {b: 1};
console.log(a);
它传递,因为接口B
有一个名为b
我希望这有助于你理解。
PS:prop指财产。
以此作为类比:Interface A
是一个空房子,无论你想要什么,都是愚蠢的。它不会说一句话。 Interface B
是一个殖民地的房子,这意味着它需要专门针对大小,形状和需要坚持Interface A
。这意味着接口B不再是空的,并受到规则的限制。
答案 2 :(得分:0)
这是结构类型在Typescript中的工作方式。它基于结构子类型。
简而言之
如果B
实现A
所需的所有成员,则B
的实例与A
兼容。
由于A
不需要任何成员,因此所有对象都与A
兼容。
答案 3 :(得分:0)
是的,官方文档中有一个解释。不是错误,而是令人惊讶的行为。本文microsoft/TypeScript - Why are all types assignable to empty interfaces?解释了这种行为。
该文档还添加了一个补充:“通常,您永远都不会发现自己声明了没有属性的接口。”