这背后的原因是因为打字稿中的类型系统工作在结构类型系统上。类型的想法有点像“契约”,其中设置规则来表明某些类型与某些类型兼容。仅当合同被破坏时,编译器才会出错。
例如:
abstract class Base{
abstract sayHello(): void;
}
class Child extends Base{
sayHello(): number {
return 123;
}
}
这是有效的,因为即使我们的方法在实现它时返回数字,所有使用sayHello()
并期望它返回一个 void 不会有任何副作用,没有合同被破坏。这只是因为 Microsft 在 typescript 中设置了一条规则,规定 void 返回类型与 number 返回类型兼容。原因就像我之前说的,它没有任何副作用,一切都是你所期望的sayHello()
返回 void 应该仍然可以按预期工作。
另一方面,如果我做了这样的事情:
abstract class Base{
abstract sayHello(): number;
}
class Child extends Base{
sayHello(): void {
return;
}
}
这会出错,因为现在使用的所有内容sayHello()
并预计它会受到影响,类型契约已被破坏,从而导致编译器错误。
您可以将其视为类型系统中的灵活性功能,但需要权衡意外类型等效性。
在像 C# 这样使用名义类型系统的语言中,它不允许我们拥有一个抽象 void 方法,该方法在实现时返回一个字符串,因为它注重类型等效性,类型必须相同才能相互兼容。
希望这可以帮助!
结构类型系统:https://en.wikipedia.org/wiki/Structural_type_system https://en.wikipedia.org/wiki/Structural_type_system
标称类型系统:https://en.wikipedia.org/wiki/Nominal_type_system https://en.wikipedia.org/wiki/Nominal_type_system
打字稿类型兼容性:https://www.typescriptlang.org/docs/handbook/type-compatibility.html https://www.typescriptlang.org/docs/handbook/type-compatibility.html
Spec: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3114-assignment-compatibility https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3114-assignment-compatibility