如何在接口声明中使用PromiseConstructorLike实例的原型?

poc*_*sar 12 typescript typescript-typings typescript2.0

我正在尝试为节点编写Google Maps帮助程序模块的声明,但是我遇到了库期望的PromiseConstructorLike问题,并正确地返回它的"PromiseLike"实例方法(根据https://googlemaps.github.io /google-maps-services-js/docs/module-@google_maps.html):

Promise     function    <optional>  Promise constructor (optional).
Run Code Online (Sandbox Code Playgroud)

所以我做了(剥离到有趣的位):

declare namespace GoogleMaps {
  export interface CreateClientOptions<T> {
    /** Promise constructor (optional). */
    Promise?: T; 
  }

  export interface GoogleMapsClient<T> {
    directions<U>(query, callback?: ResponseCallback<U>): RequestHandle<U, T>;
  }

  export interface Response<U extends any> {
      headers: any;
      json: U;
      status: number;
  }

  export interface RequestHandle<U, T extends PromiseLike<Response<U>>> {
      asPromise(): T;
      cancel(): void;
      finally(callback: ResponseCallback<U>): void;
  }

  export type ResponseCallback<U> = (err: Error, result: Response<U>) => void; 
  export function createClient<T extends PromiseConstructorLike>(options: CreateClientOptions<T>): GoogleMapsClient<T>;
}

declare module '@google/maps' {
  export = GoogleMaps
}
Run Code Online (Sandbox Code Playgroud)

当然它不起作用,如果我使用例如,蓝鸟在createClientas

import * as bluebird from 'bluebird'
import { createClient } from '@google/maps'

createClient({ Promise: bluebird }).directions({}).asPromise()/** no "then" here, just the static methods from Bluebird, like Bluebird.all */
Run Code Online (Sandbox Code Playgroud)

问题是:

反正我是否可以提示asPromise从bluebird返回实例方法(然后,catch,finally,reduce,timeout等),而不必RequestHandle手动扩展接口?

更多信息(lib.d.ts声明):

PromiseConstructorLike 是:

 declare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;
Run Code Online (Sandbox Code Playgroud)

PromiseLike 是:

interface PromiseLike<T> {
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onfulfilled The callback to execute when the Promise is resolved.
     * @param onrejected The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of which ever callback is executed.
     */
    then(
        onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null,
        onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): PromiseLike<T>;
}
Run Code Online (Sandbox Code Playgroud)

poc*_*sar 0

随着 Typescript 2.8 的发布,新的“infer”关键字使这成为可能!它可以推断(并传递)复杂的嵌套声明,解释器将尝试为您提取信息,从而提供非常好的强类型体验。

所以,如果你想获取构造函数的类型

class MyPromise extends Promise<any> implements PromiseLike<any> {
    add(s: number) {
        s++
        return this
    }
    dummy() {
        return this
    }
}

function typedFactory<
    U extends PromiseConstructorLike,
>(u: U): InstanceType<U> {
    return new u<void>(() => { }) as any 
    // this isn't needed since we are just trying to show the functionality, 
    // would be interfacing another library through types only, so that 
    // the compiler doesn't b*tch about it
}

typedFactory(Promise).then(() => { })
typedFactory(MyPromise).add(1).dummy().then(() => {})
Run Code Online (Sandbox Code Playgroud)

新的InstanceType实际上可用lib.es5.d.ts并定义为:

type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
Run Code Online (Sandbox Code Playgroud)

它显示了关键字的真正威力,您可以在https://www.typescriptlang.org/play/infer中尝试一下