typescript - 如何在接口(interface)声明中使用 PromiseConstructorLike 实例的原型(prototype)?

标签 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).

所以我做了(精简到有趣的部分):

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 as

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 返回实例方法(then、catch、finally、reduce、timeout 等)而无需扩展 手动请求处理接口(interface)?

更多信息(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>;
}

最佳答案

您的声明包含一个编译错误,这是由于混淆了 Promise 实例 类型和 Promise 构造函数 类型。类型参数 TGoogleMapsClient用于填充TRequestHandle , 然而在 GoogleMapsClient这代表 Promise构造函数类型,而在 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在两个CreateClientOptionsGoogleMapsClient ,所以传递的类型安全 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示例有效,您可以调用 then()asPromise() 之后.

关于typescript - 如何在接口(interface)声明中使用 PromiseConstructorLike 实例的原型(prototype)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40481641/

相关文章:

typescript - 如何在 AngularFire 中使用文档 ID 查询文档?

visual-studio - 我可以在一台计算机上安装多个版本的 Typescript 吗?

typescript - 箭头样式用户定义的类型防护?

javascript - Angular , typescript 注释不起作用

javascript - 我应该声明什么值类型的对象变量

node.js - tsc 报告错误 TS2318 : Cannot find global type 'Boolean'

javascript - 无法访问 typescript 中的全局变量

node.js - 无法导入代理的类型

angular - Ng2智能表,从一个对象中获取多列

node.js - 错误 : TypeError: Cannot read property 'create' of undefined on stripe. 文件上传.create