使用自定义承诺作为泛型类型

vit*_*y-t 9 promise typescript bluebird

我有一个环境TypeScript模块代表一个支持任何Promises/A +库的库:

interface Test {
  funcName():Promise<string>;
}
Run Code Online (Sandbox Code Playgroud)

所以我需要调整它,以便在声明级别上访问任何promise库的协议:

interface Test<P> {
  funcName():P<string>;
}
Run Code Online (Sandbox Code Playgroud)

但TypeScript立即抱怨:Type 'P' is not generic在我使用它之前.

请注意,我不能将自定义promise库包含在同一个文件中Test,因为我必须从另一个模块中传入它.

如果我将代码更改为:

interface AnyPromise<T, P extends Promise<T>> {
}

interface Test<P> {
    funcName():AnyPromise<string, P<string>>;
}
Run Code Online (Sandbox Code Playgroud)

它也在error TS2315: Type 'P' is not generic.这部分内抱怨:P<string>.

最后,我需要能够做到这样的事情:

import * as promise from 'bluebird'; // from Bluebird ambient declarations 
import {Test} from 'test';

var Test<promise> t; // plus initialize it;

t.funcName().finally(())=>{
}); // NOTE: 'finally' is to be visible from Bluebird (doesn't exist in ES6 Promise)
Run Code Online (Sandbox Code Playgroud)

为了再次澄清,我使用Bluebird作为示例,因为我需要一个支持任何promise库的解决方案,而不是一个特定的.

Gor*_*sev 5

这需要更高的kinded类型才能在TypeScript中着陆.跟踪它们的问题在这里:

https://github.com/Microsoft/TypeScript/issues/1213

截至2016年4月,尚未实现.

您可以使用产品类型对其中的一些进行近似,但需要对PromiseLike类型进行修改,并且您需要then在库中使用时随时显式传递类型参数:

interface HKPromiseLike<T> {
    then<TResult, P>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): P & HKPromiseLike<TResult>;
    then<TResult, P>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): P & HKPromiseLike<TResult>;
}

class Wrapper<T, P> {
    constructor(public p:P & HKPromiseLike<T>) {}

    map<U>(f:(t:T) => U) {
        var res = this.p.then<U, P>(f)
        var w = new Wrapper(res);
        return w
    }
}
Run Code Online (Sandbox Code Playgroud)

要专门化这个包装器,必须使用class/extends.

class Specialized<T> extends Wrapper<T, SomePromise<T>> { }
Run Code Online (Sandbox Code Playgroud)

  • 是.我已经对这个问题添加了评论,所以没关系:) (2认同)