在 TypeScript 中使用带有 ES6 Promise 的 thenable 接口

Kre*_*nor 0 typescript es6-promise typescript-typings ajv

一些库提供Thenable接口类型 fe AJV
我对他们有些不明白。鉴于这个最少的代码

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

  reject("Nope")
})
Run Code Online (Sandbox Code Playgroud)

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'.
Run Code Online (Sandbox Code Playgroud)

编译器认为TypeScripts ES6 Promise到底会在哪里返回null(如果那是实际的错误)?
为什么有些库(bluebird、rsvp、ember 等)使用Thenable不是Promise/ PromiseLike

Pas*_*asi 5

Ajv 的Thenable类型声明表示,then通常称为 的第二个参数在调用时必须返回与第一个参数onRejected相同的类型。ES6 承诺,因此 TypeScript 的/没有这样的限制。<U>onFulfilledPromisePromiseLike

例如,在这段代码中:

const p1: PromiseLike<boolean> = /* ... */
const p2 = p1.then(() => true, () => 123)
Run Code Online (Sandbox Code Playgroud)

TypeScript 将(正确地)推断出 p2 具有类型PromiseLike<number | boolean>。使用 Ajv 的Thenable类型声明,等效代码将无法编译,因为 123 不能分配给 boolean。

实际的 AJV JavaScript 代码似乎返回正常的 Promises,因此它不关心类型。所以这对我来说似乎是 AJV 的 TypeScript 声明中的一个错误...我不知道为什么 AJV 不在这里使用 TypeScript 的内置PromiseLike...