【问题标题】:Using a custom promise as a generic type使用自定义 Promise 作为泛型类型
【发布时间】:2016-08-04 05:39:12
【问题描述】:

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

interface Test {
  funcName():Promise<string>;
}

所以我需要调整它,使任何 Promise 库的协议都可以在声明级别访问:

interface Test<P> {
  funcName():P<string>;
}

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

请注意,我不能将自定义 Promise 库包含到与 Test 相同的文件中,因为我必须从另一个模块传入它。

如果我把代码改成这样:

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

interface Test<P> {
    funcName():AnyPromise<string, P<string>>;
}

它还在这部分抱怨error TS2315: Type 'P' is not generic.P&lt;string&gt;

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

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)

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

【问题讨论】:

  • 为什么Test&lt;typeof promise&gt;,不应该只是Test&lt;promise&gt;吗?
  • @Bergi 告诉编译器将变量视为一个类。但这没关系,因为错误发生在该调用之前,同时解析类Test。我已经更新了问题;)
  • 你需要定义一个thenable 结构接口,虽然我认为 bluebird 在结构上会作为 ES2015 承诺传递,因为它具有完全相同的函数签名。
  • @BenjaminGruenbaum Bluebird 在我想要访问的标准 Promise 协议之上有很多额外的方法,所以我试图弄清楚如何将它作为动态参数模板化.
  • 哦,你想让返回的promise的类型依赖于输入promise的类型吗?我不认为 TS 会这样做,但我会 ping @spion,他实际上是地球上唯一对此深感兴趣的人:P(更新:在一些人认为用泛型建模听起来不太难之后总的来说,我知道我可以在 C++ 中轻松做到这一点)

标签: typescript promise bluebird


【解决方案1】:

这需要更高种类的类型才能登陆 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
    }
}

要专门化此包装器,您必须使用类/扩展。

class Specialized<T> extends Wrapper<T, SomePromise<T>> { }

【讨论】:

  • 浏览 TypeScript 功能的进展,看到它的前景相当暗淡。
  • 有人要求我实现这个功能,但我一次又一次地失败了。只是犹豫说不,这是不可能的,因为我缺乏 TypeScript 知识。现在我有信心说这实际上是不可能的,而且我在我的库中这样做是唯一(虽然丑陋)的方法——使用自定义承诺手动修补:github.com/vitaly-t/pg-promise/blob/master/typescript/…。谢谢你的澄清!
  • 我建议对 TypeScript 问题发表评论并在此处添加您的问题。它将向 TS 团队展示这些功能很有用,而不仅仅适用于 FP 样式代码...
  • TypeScript 2.0 也做不到。如果您检查问题,您可以看到它仍然处于打开状态。
  • 更高种类的泛型问题仍然存在,所以我不相信它。
猜你喜欢
  • 1970-01-01
  • 2011-08-16
  • 2021-12-06
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
相关资源
最近更新 更多