【问题标题】:Typescript overriding abstract method which is void return打字稿覆盖抽象方法是无效返回
【发布时间】:2020-04-17 11:15:39
【问题描述】:
abstract class Base{
    abstract sayHello(): void;
}

class Child extends Base{
    sayHello() {
        return 123;
    }
}

抽象方法的返回类型是 void 但我可以用数字类型返回来实现它。 我没有从编译器中得到任何错误。 Typescript 有这种 bug 吗?

TS Spec

void 关键字引用的 Void 类型,表示缺席 一个值,用作没有返回的函数的返回类型 价值。

【问题讨论】:

    标签: typescript abstract-class abstract-methods


    【解决方案1】:

    这背后的原因是打字稿中的类型系统在结构类型系统上工作。类型的概念有点像“合同”,其中规则被设置为说某些类型与某些类型兼容。如果合约被破坏,编译器只会出错。 比如:

    abstract class Base{
        abstract sayHello(): void;
    }
    
    class Child extends Base{
        sayHello(): number {
            return 123;
        }
    }
    

    这是可行的,因为即使我们的方法在我们实现它时返回数字,所有使用 sayHello() 并期望它返回 void 的东西都不会产生副作用,也不会破坏任何合同。这仅仅是因为 Microsft 在 typescript 中设置了一条规则,说明 void 返回类型与数字返回类型兼容。原因正如我之前所说,它没有副作用,所有期望 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/Nominal_type_system

    Typescript 类型兼容性:https://www.typescriptlang.org/docs/handbook/type-compatibility.html

    规格:https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3114-assignment-compatibility

    【讨论】:

    • 感谢您的详细解答。我浏览了您的参考链接。但它们对我来说不清楚或太复杂。我们已经有了“any”类型来签署函数以返回任何内容,并且我们知道所有函数都返回“undefined”,即使它们没有 return 语句。所以我们可以使用'undefined'而不是'void'。虚无没有任何意义,它只是疯狂和烧脑。
    【解决方案2】:

    quoteRyan Cavanaugh TS 首席开发人员:

    返回类型为 void 的函数引用的返回值可以是任何值,因为非返回 void 的函数可以使用返回 void 的类型的别名。

    所以事情是关于返回void类型 函数,可以接受(被分配)返回任何东西的 函数。

    type ReturnVoid = () => void
    
    const foo: ReturnVoid = () => 42  // all good
    

    此行为在 Assignment Compatibility 部分中指定

    M 是一个非特化的调用或构造签名,而 S 有一个明显的调用或构造签名 N 其中,[...] M 的结果类型是 Void,或N 可分配给 M

    参考资料:

    1. https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-functions-returning-non-void-assignable-to-function-returning-void
    2. https://github.com/microsoft/TypeScript/issues/21674

    【讨论】:

    • 我明白了,但它没有意义。
    • 这对我来说很有意义。 Return void 实际上意味着可以安全地忽略返回值。因此,我是否返回任何东西都没有关系。
    • 还要考虑事件处理程序。 .on(“click”, e => void) 大多数时候回调签名返回无效。如果我有一个返回布尔值的现成函数,但它可以作为这个事件处理程序工作,只是签名有点偏离怎么办?如果我把它传进去,我不希望 TS 对我大喊大叫。
    • 我认为 Typescript 规范对此并不清楚。 void关键字引用的void类型,表示没有值,用作没有返回值的函数的返回类型。
    • 但是,Child.sayHello 确实会输入到numberPlayground
    猜你喜欢
    • 1970-01-01
    • 2020-12-22
    • 2020-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 2014-06-20
    • 2014-01-16
    相关资源
    最近更新 更多