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

时间:2016-11-08 07:55:20

标签: typescript typescript-typings typescript2.0

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

Promise     function    <optional>  Promise constructor (optional).

所以我做了(剥离了有趣的部分):

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
}

当然,如果我使用createClient中的Bluebird作为

,它就不起作用了
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 */

问题是:

无论如何,我可以提示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>;

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>;
}

2 个答案:

答案 0 :(得分:1)

您的声明包含编译错误,该错误源于混淆Promise 实例类型和Promise 构造函数类型。 T中的类型参数GoogleMapsClient用于填充T中的RequestHandle,但在GoogleMapsClient中,这表示Promise构造函数类型,而在{ {1}}它代表RequestHandle实例类型。

您似乎打算根据Promise 实例类型Promise正确输入所有内容,其中PromiseLike<Response<U>>是响应类型。但是,由于事先不知道U(即在致电U之前),因此遗憾的是不可能。

如果您想在GoogleMapsClient.directions之后致电then(),只需将asPromise()的返回类型更改为RequestHandle.asPromise,然后移除类型参数PromiseLike<Response<U>>

T

我个人还会在export interface RequestHandle<U> { asPromise(): PromiseLike<U>; cancel(): void; finally(callback: ResponseCallback<U>): void; } extends PromiseConstructorLike中添加约束T到参数CreateClientOptions,以便传递{{1}的类型安全性构造函数不仅仅依赖于GoogleMapsClient中指定的约束。

总而言之,声明现在如下所示:

Promise

通过这些声明,您的createClient示例有效,您可以在declare namespace GoogleMaps { export interface CreateClientOptions<T extends PromiseConstructorLike> { /** Promise constructor (optional). */ Promise?: T; } export interface GoogleMapsClient<T extends PromiseConstructorLike> { directions<U>(query, callback?: ResponseCallback<U>): RequestHandle<U>; } export interface Response<U extends any> { headers: any; json: U; status: number; } export interface RequestHandle<U> { asPromise(): PromiseLike<Response<U>>; 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 } 之后致电bluebird

答案 1 :(得分:0)

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

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

    if (instance == null) {
    throw new IllegalStateException("this application does not 
    inherit GlobalApplication"); " +
    "}

    return instance;
    }

    Step4)
    g.setAdapter(new ImageAdapter(getGlobalApplicationContext()));

新的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(() => {}) 实际上在InstanceType中可用,并且定义为:

lib.es5.d.ts

它显示了type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any; 关键字的真实功能,您可以在https://www.typescriptlang.org/play/中尝试