如何在 TypeScript 中继承 PromiseLike 接口?

Posted

技术标签:

【中文标题】如何在 TypeScript 中继承 PromiseLike 接口?【英文标题】:How to inherit PromiseLike interface in TypeScript? 【发布时间】:2020-01-29 18:17:15 【问题描述】:

我想扩展 PromiseLike 接口。

(我使用 TypeScript v3.6.3)

我取了原来的PromiseLike接口:

interface PromiseLike<T> 
    then<TResult1 = T, TResult2 = never>(
        onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
        onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,
    ): PromiseLike<TResult1 | TResult2>

那我只继承 PromiseLike 并将嵌套的 PromiseLike 类型替换为 Thenable:

interface Thenable<T = any> extends PromiseLike<T> 
    then<TResult1 = T, TResult2 = never>(
        onfulfilled?: ((value: T) => TResult1 | Thenable<TResult1>) | undefined | null,
        onrejected?: ((reason: any) => TResult2 | Thenable<TResult2>) | undefined | null,
    ): Thenable<TResult1 | TResult2>

得到了这个错误:

Error:(28, 18) TS2430: Interface 'Thenable<T>' incorrectly extends interface 'PromiseLike<T>'.
  Types of property 'then' are incompatible.
    Type '<TResult1 = T, TResult2 = never>(onfulfilled?: (value: T) => TResult1 | Thenable<TResult1>, onrejected?: (reason: any) => TResult2 | Thenable<TResult2>) => Thenable<TResult1 | TResult2>' is not assignable to type '<TResult1 = T, TResult2 = never>(onfulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>'.
      Types of parameters 'onrejected' and 'onrejected' are incompatible.
        Type 'TResult2 | PromiseLike<TResult2>' is not assignable to type 'TResult2 | Thenable<TResult2>'.
          Type 'PromiseLike<TResult2>' is not assignable to type 'TResult2 | Thenable<TResult2>'.
            Type 'PromiseLike<TResult2>' is not assignable to type 'Thenable<TResult2>'.
              Types of property 'then' are incompatible.
                Type '<TResult1 = TResult2, TResult2 = never>(onfulfilled?: (value: TResult2) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>' is not assignable to type '<TResult1 = TResult2, TResult2 = never>(onfulfilled?: (value: TResult2) => TResult1 | Thenable<TResult1>, onrejected?: (reason: any) => TResult2 | Thenable<TResult2>) => Thenable<TResult1 | TResult2>'.
                  Types of parameters 'onrejected' and 'onrejected' are incompatible.
                    Type 'TResult2 | Thenable<TResult2>' is not assignable to type 'TResult2 | PromiseLike<TResult2>'.
                      Type 'Thenable<TResult2>' is not assignable to type 'TResult2 | PromiseLike<TResult2>'.
                        Type 'Thenable<TResult2>' is not assignable to type 'PromiseLike<TResult2>'.
                          Types of property 'then' are incompatible.
                            Type '<TResult1 = TResult2, TResult2 = never>(onfulfilled?: (value: TResult2) => TResult1 | Thenable<TResult1>, onrejected?: (reason: any) => TResult2 | Thenable<TResult2>) => Thenable<TResult1 | TResult2>' is not assignable to type '<TResult1 = TResult2, TResult2 = never>(onfulfilled?: (value: TResult2) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>'.
                              Types of parameters 'onrejected' and 'onrejected' are incompatible.
                                Type 'TResult2 | PromiseLike<TResult2>' is not assignable to type 'TResult2 | Thenable<TResult2>'.
                                  Type 'PromiseLike<TResult2>' is not assignable to type 'TResult2 | Thenable<TResult2>'.

如何解决这个错误?

此外,我想像这样扩展这个接口:

export interface Thenable<T = any> extends PromiseLike<T> 
    then<TResult1 = T, TResult2 = never>(
        onfulfilled?: ((value: T) => TResult1 | ThenableOrIteratorOrValue<TResult1>) | undefined | null,
        onrejected?: ((reason: any) => TResult2 | ThenableOrIteratorOrValue<TResult2>) | undefined | null,
    ): ThenableOrIteratorOrValue<TResult1 | TResult2>

并且我希望它与 PromiseLike 保持兼容,以便异步等待功能与之兼容。

【问题讨论】:

您不能扩展接口并覆盖属性。请看***.com/questions/41285211/… 为什么要扩展 PromiseLike 接口?你想达到什么目标?谢谢 我使用生成器(yield 而不是 await)实现了异步函数的同步版本。我使用 Iterator 类型作为同步 Promise。现在我想结合所有类似接口的承诺。 union 类型会有帮助吗?我不知道您的ThenableOrIteratorOrValue&lt;T&gt; 的代码。也许以下内容可以帮助您:type PromiseLikeOrThenable&lt;T&gt; = PromiseLike&lt;T&gt; | Thenable&lt;T&gt; | IteratorResult&lt;T&gt;; 【参考方案1】:

保持与PromiseLike 兼容意味着您的Thenable 可以作为参数传递给需要PromiseLike 的代码,并且该代码仍然可以工作。为此,then 应该接受返回PromiseLikeonfulfilled 回调,而不是您的Thenable - 因为这是使用PromiseLike 的代码将传递给您的then 实现的回调类型。

因此,将PromiseLike 添加到可以由回调返回的类型联合中,这样错误就会消失:

    onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,

由于我不明白的原因,onrejected 是兼容的,显然是因为它的类型不依赖于泛型参数T

【讨论】:

以上是关于如何在 TypeScript 中继承 PromiseLike 接口?的主要内容,如果未能解决你的问题,请参考以下文章

Typescript中继承的父类中的参数是啥?

如何在 Swift 中继承 UITableViewController

如何在一个类中继承 QGraphicsRectItem 和 QGraphicsEllipseItem?

如何在 python 中继承类型提示?

如何在 JavaScript 中继承 C++ 类?

如何在 GraphQL 中继承或扩展 typeDef