【问题标题】:Making an interface generic over promise libraries在 Promise 库上创建一个通用接口
【发布时间】:2019-01-26 08:20:58
【问题描述】:

我正在为es6-promise-pool 编写定义以添加到DefiniteTyped,并从the discussion at GitHub 进行一些调整。该库可以采用可选的promise 参数,该参数指定用于返回的承诺的类(例如ES6-Promise 的polyfill 或Bluebird)。在内部,它关心的只是你可以call new Promise(…),所以这足以指定值的类型:

interface PromiseClass<A, P extends PromiseLike<A>> {
    new(callback: (resolve: (value?: A | P) => void, reject: (reason?: any) => void) => void): P;
}

const bar: PromiseClass<number, Bluebird<number>> = Bluebird; // OK

问题的关键在于指定选项的类型:

interface Options<A, P extends PromiseLike<A>, C extends PromiseClass<A, P>> {
    promise?: C;
}

function foo<A, P extends PromiseLike<A>, C extends PromiseClass<A, P>>(options: Options<A, P, C>) { /* empty */ }

foo({ promise: Bluebird.resolve(3) });

这给了我一个错误:

'{ promise: Bluebird; 类型的参数}' 不可分配给“Options, PromiseClass>>”类型的参数。
  财产“承诺”的类型是不相容的。
    类型“Bluebird”不可分配给类型“PromiseClass> |不明确的'。
      类型“Bluebird”不可分配给类型“PromiseClass>”。
        类型 'Bluebird' 不匹配签名 'new (callback: (resolve: (value?: {} | PromiseLike | undefined) => void, reject: (reason?: any) => void) => void): PromiseLike'。

(注意类型被推断为{}。)

如果我手动指定类型:

foo<number, Bluebird<number>, PromiseClass<number, Bluebird<number>>>({ promise: Bluebird.resolve(3) });

我收到类似的错误:

'{ promise: Bluebird; 类型的参数}' 不可分配给“Options, PromiseClass>>”类型的参数。
  财产“承诺”的类型是不兼容的。
    类型“蓝鸟”不可分配给类型“PromiseClass> |不明确的'。
      类型“Bluebird”不可分配给类型“PromiseClass>”。
        类型 'Bluebird' 不匹配签名 'new (callback: (resolve: (value?: number | PromiseLike | undefined) => void, reject: (reason?: any) => void) => void): Bluebird '。

这里是the relevant definitions from DefinitelyTyped,当类型被正确推断时应该是兼容的:

type Resolvable<R> = R | PromiseLike<R>;

constructor(callback: (resolve: (thenableOrResult?: Resolvable<R>) => void, reject: (error?: any) => void, onCancel?: (callback: () => void) => void) => void);

对于上下文,这是我使用类型的方式(省略不相关的方法):

declare class PromisePool<
    A,                        // the type of value returned by the source
    P extends PromiseLike<A>, // the type of Promise returned by the source
    P2 extends PromiseLike<A>, // the type of Promise specified in `options`
    C extends PromisePool.PromiseClass<A, P2> // a helper class
    > {
    constructor(
        source: IterableIterator<P> | P | (() => (P | undefined)) | A,
        concurrency: number,
        options?: PromisePool.Options<A, P2, C>
    );

    promise(): P2;
    start(): P2;
}

declare namespace PromisePool {
    interface PromiseClass<A, P extends PromiseLike<A>> {
        new(callback: (resolve: (value?: A | P) => void, reject: (reason?: any) => void) => void): P;
    }

    interface Options<A, P extends PromiseLike<A>, C extends PromiseClass<A, P>> {
        promise?: C;
    }
}

如何指定Options 类型以便:

  • 可以指定任何newable 承诺库(如上),并自动推断类型
  • 如果未指定,则回退到 Promise
  • 我可以将promise类型指定为PromisePool.promisePromisePool.start的返回值

【问题讨论】:

    标签: typescript definitelytyped


    【解决方案1】:

    我误用了我自己的类型,因为我认为Bluebird.resolve(3) 的功能与Bluebird 相同,尽管我陷入这种混乱是为了区分两者。无论如何,这是可行的:

    import Bluebird = require("bluebird");
    import ES6Promise = require("es6-promise");
    
    interface PromiseClass<A, P extends PromiseLike<A>> {
        new(callback: (resolve: (value?: A | P) => void, reject: (reason?: any) => void) => void): P;
    }
    
    interface Options<A, P extends PromiseLike<A>, C extends PromiseClass<A, P>> {
        promise?: C;
    }
    
    function foo<A, P extends PromiseLike<A>, C extends PromiseClass<A, P>>(options: Options<A, P, C>, val: A): P {
        return new options.promise((resolve, reject) => resolve(val));
    }
    
    const baz: Bluebird<number> = foo({ promise: Bluebird }, 5);
    const quux: ES6Promise.Promise<number> = foo({ promise: ES6Promise.Promise }, 5);
    

    我只需要将类作为promise 的值传递,而不是实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2017-06-22
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      相关资源
      最近更新 更多