空接口允许任何对象?

时间:2017-03-01 17:02:23

标签: typescript

为什么空接口不要求对象为空?

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'结束。

  • 如果接口定义了对象必须具有的属性,则B case应该可以正常工作,所有必需的属性都存在。
  • 如果接口定义了对象可以具有的属性,则案例应该导致错误,接口中未定义a

非空接口定义了哪个对象可以和必须具有。 空接口的行为类似于any

是否有解释为什么空接口的行为如下?这是故意还是只是一个错误?

4 个答案:

答案 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

如果您的类型为空,则忽略此约束。

了解更多herehere

来自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);

失败,因为在AB接口内没有名为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兼容。

this documentation

中的完整详情

答案 3 :(得分:0)

是的,官方文档中有一个解释。不是错误,而是令人惊讶的行为。本文microsoft/TypeScript - Why are all types assignable to empty interfaces?解释了这种行为。

该文档还添加了一个补充:“通常,您永远都不会发现自己声明了没有属性的接口。”