Использование интерфейсов с возможностью последующего просмотра с обещаниями ES6 в TypeScript

Некоторые библиотеки предлагают Thenable Интерфейсный набор, например, AJV.
Есть что-то, чего я не понимаю в них. Учитывая этот минимальный код

const foo: Ajv.Thenable<boolean> = new Promise<boolean>((resolve, reject) => {
  if ("condition")
    resolve(true)

  reject("Nope")
})

компилятор TypeScript выдает ошибку, которую я не могу обернуть вокруг.

error TS2322: Type 'Promise<boolean>' is not assignable to type 'Thenable<boolean>'.
  Types of property 'then' are incompatible.
    Type '<TResult1 = boolean, TResult2 = never>(onfulfilled?: ((value: boolean) => TResult1 | PromiseLike<...' is not assignable to type '<U>(onFulfilled?: ((value: boolean) => U | Thenable<U>) | undefined, onRejected?: ((error: any) =...'.
      Types of parameters 'onfulfilled' and 'onFulfilled' are incompatible.
        Type '((value: boolean) => U | Thenable<U>) | undefined' is not assignable to type '((value: boolean) => U | PromiseLike<U>) | null | undefined'.
          Type '(value: boolean) => U | Thenable<U>' is not assignable to type '((value: boolean) => U | PromiseLike<U>) | null | undefined'.
            Type '(value: boolean) => U | Thenable<U>' is not assignable to type '(value: boolean) => U | PromiseLike<U>'.
              Type 'U | Thenable<U>' is not assignable to type 'U | PromiseLike<U>'.
                Type 'Thenable<U>' is not assignable to type 'U | PromiseLike<U>'.
                  Type 'Thenable<U>' is not assignable to type 'PromiseLike<U>'.
                    Types of property 'then' are incompatible.
                      Type '<U>(onFulfilled?: ((value: U) => U | Thenable<U>) | undefined, onRejected?: ((error: any) => U | ...' is not assignable to type '<TResult1 = U, TResult2 = never>(onfulfilled?: ((value: U) => TResult1 | PromiseLike<TResult1>) |...'.
                        Types of parameters 'onFulfilled' and 'onfulfilled' are incompatible.
                          Type '((value: U) => TResult1 | PromiseLike<TResult1>) | null | undefined' is not assignable to type '((value: U) => TResult2 | Thenable<TResult2>) | undefined'.
                            Type 'null' is not assignable to type '((value: U) => TResult2 | Thenable<TResult2>) | undefined'.

Где именно компилятор думает, что вернется обещание TypeScripts ES6 null (если это фактическая ошибка)?
И почему некоторые библиотеки (bluebird, rsvp, ember, ...) используют Thenable вместо Promise / PromiseLike?

1 ответ

Решение

AJV-х Thenable объявление типа говорит, что второй параметр thenобычно называется onRejectedпри вызове должен возвращать тот же тип <U> как первый onFulfilled параметр. ES6 обещает, и, следовательно, TypeScript's Promise/PromiseLikeНет такого ограничения.

Например, в этом коде:

const p1: PromiseLike<boolean> = /* ... */
const p2 = p1.then(() => true, () => 123)

TypeScript (правильно) выведет, что p2 имеет тип PromiseLike<number | boolean>, С Айв Thenable объявление типа, эквивалентный код не удастся скомпилировать, потому что 123 не может быть присвоено логическому.

Реальный код JavaScript AJV, похоже, возвращает нормальные обещания, поэтому он не заботится о типах. Так что это похоже на ошибку в декларациях TypeScript AJV для меня... Я не знаю, почему AJV не использует встроенный TypeScript PromiseLike Вот...

Другие вопросы по тегам