Как наследовать интерфейс PromiseLike в TypeScript? - PullRequest
0 голосов
/ 30 сентября 2019

Я хочу расширить интерфейс 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, чтобы функции асинхронного ожидания были совместимы с ним.

1 Ответ

0 голосов
/ 30 сентября 2019

Совместимость с PromiseLike означает, что ваш Thenable может быть передан в качестве параметра к коду, который ожидает PromiseLike, и этот код все еще должен работать. Чтобы это работало, then должен принять onfulfilled обратный вызов, который возвращает PromiseLike, а не ваш Thenable - потому что это тип обратного вызова, который код, который использует PromiseLike, передаст вашей реализации then.

Итак, добавление PromiseLike к объединению типов, которые могут быть возвращены обратным вызовом, как это, устраняет ошибку:

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

По причинам, которые я не понимаю,onrejected совместим как есть, очевидно, потому что его тип не зависит от универсального параметра T.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...