这在typescript中失败。。。
interface A {
getSomeBasicA():A;
getSomeBetterA():BetterA;
}
interface BetterA extends A {
getSomeBasicA():BetterA;
doFancyAStuff():void;
}
interface B extends A {
getSomeBetterA():BetterB;
}
interface BetterB extends B, BetterA {}
... 带着这个信息。。。
error TS2430: Interface 'B' incorrectly extends interface 'A'.
The types returned by 'getSomeBetterA().getSomeBasicA()' are incompatible between these types.
Property 'doFancyAStuff' is missing in type 'A' but required in type 'BetterA'.
error TS2320: Interface 'BetterB' cannot simultaneously extend types 'B' and 'BetterA'.
Named property 'getSomeBasicA' of types 'B' and 'BetterA' are not identical.
error TS2320: Interface 'BetterB' cannot simultaneously extend types 'B' and 'BetterA'.
Named property 'getSomeBetterA' of types 'B' and 'BetterA' are not identical.
... 虽然这在java中有效。。。
public interface A {
public A getSomeBasicA();
public BetterA getSomeBetterA();
}
public interface BetterA extends A {
public BetterA getSomeBasicA();
public void doFancyAStuff();
}
public interface B extends A {
public BetterB getSomeBetterA();
}
public interface BetterB extends B, BetterA {
}
... 我想知道为什么?它不是类型安全的吗(它怎么可能被破坏,为什么java编译器允许它)?有一个编译器支持而另一个不支持的特性的名称吗?
2条答案
按热度按时间s4n0splo1#
仅仅因为它在java中工作并不意味着它应该在typescript上工作。这是两件完全不同的事情。对于初学者来说,typescript依赖于duck类型,而java则不依赖。
如果您想组合多个接口,最好使用Map类型,而不是多次扩展。
我在媒体上写的,看看,可能会有帮助
toiithl62#
如您所见,typescript要求在通过逗号表示法扩展多个接口时(例如。,
interface X extends Y, Z { ... }
),多个父接口共用的任何成员名称都需要具有相同的类型。定义
BetterB
违反这一限制;它不能同时声明为B
以及BetterA
.B
有一个getBasicA
类型的成员() => A
,而BetterA
有一个getBasicA
类型的成员() => BetterA
. 这些类型是不相同的,因此会出现一个错误,最终导致整个问题的解决,因为接口定义是递归的。要求多个接口的扩展中的公共属性具有相同的类型,这可能比它需要的限制性更强。microsoft/typescript#16936上有一个开放的特性请求,请求允许普通成员具有不相同但“兼容”的类型(可能意味着这些类型有一些重叠)。在这种情况下,行为应该是什么还不是100%清楚;新接口的属性类型可能是每个父接口的属性类型的交集,或者可能会发生一些更复杂的选择过程。但无论如何,它并不是ts4.1语言的一部分。
重申一下:并不是说你要做的不是类型安全的,只是不支持。
那么,你能做什么?typescript值得注意的一点是,类型系统是结构化的,而不是像java中那样是标称的。类型在typescript中是通过它们的形状进行比较的,而不是通过它们的声明。在java中,如果你不能声明
interface X extends Y, Z
,则不能使用X
当你被要求Y
或者Z
. typescript没有这样的限制:ifX
的结构与两者兼容Y
以及Z
,您可以使用X
代替Y
或者Z
即使X
没有提到Y
或者Z
明确地。这意味着如果我们能弄清楚我们希望看到什么样的成员名和类型
BetterB
,我们可以定义BetterB
没有明确说明的形状extends B, BetterA
. 如果我们做对了,它会自动扩展这些接口。我能想到的最简单的方法是:
在这里,我们仍在扩展
BetterA
,而不是显式扩展B
,我们正在使用Pick
实用类型说,我们只想扩展的一部分B
用一个getSomeBetterA
成员。冒犯者getBasicA
方法被排除,因此没有错误。从那以后呢BetterA
的getBasicA
方法可分配给B
的getBasicA
方法,BetterB
仍然延伸B
从结构上看,如图所示:分配类型的值时没有错误
BetterB
类型的变量B
. 你没有申报BetterB extends B
但事情还是发生了。操场链接到代码