考虑具有两个实现的TypeScript接口:
interface IFoo {}
class FooA implements IFoo {}
class FooB implements IFoo {}
接下来,考虑一个接受IFoo
实现作为类型参数的通用接口:
interface IFooHandler<F extends IFoo> {
handle(foo: F): string
}
现在,让我们使用IFooHandler
的特定实现作为类型参数实现IFoo
接口:
class FooAHandler implements IFooHandler<FooA> {
handle(foo: FooB): string {
return "Hello, Foo A!";
}
}
使用版本2.0.3中的tsc
完美编译。所以这是我的问题:为什么 这个编译?
请注意,我在FooB
的{{1}}函数中使用了FooAHandler
作为参数类型。我假设此代码会触发编译器错误,因为handle()
接口规定IFooHandler<F>
方法应接受handle
类型的参数(因此,如果{{1}类型F
- 和不IFooHandler<FooA>
)。
我在TypeScript文档中找不到任何关于此行为的信息。这种行为是故意的,如果是这样,背后的原因是什么?或者我只是以错误的方式使用此功能?
仅仅为了比较,在Java中实现完全相同的示例(省略代码,因为它非常相似)会产生(预期的)编译错误:
FooAHandler.java:1:错误FooAHandler不是抽象的,并且不会覆盖IFooHandler中的抽象方法句柄(FooA)
答案 0 :(得分:4)
这是因为编译器没有按名称比较类型,它会检查它们的结构,因为IFoo
,FooA
和FooB
都是空的,所以它们都是相同的。
即使在做:
interface IFoo {
a: string;
}
class FooA implements IFoo {
a: string;
}
class FooB implements IFoo {
a: string;
}
编译器仍然不会抱怨,但一旦我们区分FooA
和FooB
:
class FooA implements IFoo {
a: string;
b: string;
}
class FooB implements IFoo {
a: string;
c: string;
}
我们收到编译错误:
Class 'FooAHandler' incorrectly implements interface 'IFooHandler<FooA>'.
Types of property 'handle' are incompatible.
Type '(foo: FooB) => string' is not assignable to type '(foo: FooA) => string'.
Types of parameters 'foo' and 'foo' are incompatible.
Type 'FooA' is not assignable to type 'FooB'.
Property 'c' is missing in type 'FooA'.
旁注:
空对象(像所有接口一样)将始终接受所有内容:
interface IFoo { }
function fn(foo: IFoo) {}
fn(3); // ok
fn("string"); // ok
fn({ key: "value" }); // ok