打字稿:无法导出通用接口模块并包含其他通用接口

Gor*_*sev 9 generics module export class typescript

我正在尝试为Bluebird编写一个CommonJS声明文件,这是一个直接导出通用Promise类的promise库.但是,该库还将几个其他泛型类导出为静态成员(PromiseInspection),并且似乎无法使用typescript对其进行建模.

编辑:用法示例,用于说明模块的导出类的工作方式:

import Promise = require('bluebird');
var promise:Promise<number> = Promise.cast(5);
var x:Promise.PromiseInspection<number> = promise.inspect();
Run Code Online (Sandbox Code Playgroud)

我尝试了几种策略 - 简化示例如下:

1.显而易见的方式

declare module "bluebird" {
    class PromiseInspection<T> {
        // ...
    }
    class Promise<T> {
        PromiseInspection: typeof PromiseInspection; // error
        constructor<T>();
        inspect():PromiseInspection<T>; // error
        static cast<U>(value:U):Promise<U>; 
        // ...
    }
    export = Promise;
}
Run Code Online (Sandbox Code Playgroud)

失败,错误无法使用私有类型PromiseInspection作为公共属性

2.使用静态接口

declare module "bluebird2" {
    interface PromiseInspection<T> {
        // ...  
    }
    interface Promise<T> {
        constructor<T>();
        inspect():PromiseInspection<T>;
    }
    interface PromiseStatic {
        new<T>();
        PromiseInspection:typeof PromiseInspection;
        cast<U>(value:U):Promise<U>; // error
    }
    export = PromiseStatic;
}
Run Code Online (Sandbox Code Playgroud)

同样失败,但这次私有类型是Promise

3.尝试从模块直接导出构造函数

declare module "bluebird3" {
    export interface PromiseInspection<T> {
        // ...
    }
    export interface Promise<T> {
        constructor<T>();
        inspect():PromiseInspection<T>;
    }

    export new<T>(); // syntax error
    export function cast<U>(value:U):Promise<U>; 
}
Run Code Online (Sandbox Code Playgroud)

这几乎可以工作,当然除了这样的构造函数不可能.

4.命名空间污染方式(Works,有缺点)

interface PromiseInspection<T> {
    // ...
}
interface Promise<T> {
    constructor<T>();
    inspect():PromiseInspection<T>;
}

declare module "bluebird4" {    
    interface PromiseStatic {
        new<T>():Promise<T>;
        PromiseInspection: typeof PromiseInspection;
        cast<U>(value:U):Promise<U>;
    }
    export = PromiseStatic;
}
Run Code Online (Sandbox Code Playgroud)

Works,但它使用Promise和PromiseInspection污染全局命名空间.这可能没问题,但我宁愿避免使用它,因为在CommonJS中它通常被认为是不可接受的.

5.声明合并(让我90%的方式...)

declare module "bluebird5" {
    module Promise {
        export interface PromiseInspection<T> {
            value(): T;
            // ...
        }
        export
        function cast<U>(value: U): Promise<U> ;
    }

    class Promise<T> {
        new <T> (): Promise <T> ;
        inspect(): Promise.PromiseInspection <T> ;
    }

    export = Promise;
}
Run Code Online (Sandbox Code Playgroud)

几乎没有-除了我现在不能代替class Promise<T>interface Promise<T>,使Promise<T>unextendable.如果我尝试这样做,请使用以下代码:

import Promise = require('bluebird');
var x = new Promise<number>();
x.inspect().value().toExponential();
Run Code Online (Sandbox Code Playgroud)

失败并显示错误"无效'新'表达式"

链接到实际的,正在进行中的bluebird.d.ts - 这个当前污染全局命名空间(使用解决方案4)

有没有更好的方法来做到这一点,还是我遇到了语言限制?

Gor*_*sev 5

Anders Hejlsberg 在 CodePlex 上发布了一个答案,因此我将在此处添加它。声明合并解决方案很接近 - 但我还需要一个“var”声明来声明静态接口,因为它是唯一可以接受构造函数的接口。

declare module "bluebird" {
    module Promise {
        export interface PromiseInspection<T> {
            value(): T;
        }
    }
    interface Promise<T> {
        inspect(): Promise.PromiseInspection <T> ;
    }

    var Promise: {
        new<U>(): Promise<U>;
        cast<U>(value: U): Promise<U> ;
    }
    export = Promise;
}
Run Code Online (Sandbox Code Playgroud)

所以基本上:

  • 模块声明中的接口成员(只要它们仅声明类型,即非物理类型)
  • 主界面中的实例成员
  • var 声明中的静态函数成员、构造函数和其他“物理”成员。

另外,他的评论:

通过这种方式编写,您可以为标识符 Promise 的三种含义中的每一种含义分别声明:作为命名空间(仅包含类型的模块)、作为类型(恰好是泛型)和作为值。


Joh*_*lly 0

看着你的代码我发现你遗漏了一些export语句。下面的代码可以编译 - 它适合吗?

\n\n
declare module bluebird {\n    export class PromiseInspection<T> {\n        // ...\n    }\n    export class Promise<T> {\n        constructor<T>();\n        inspect():PromiseInspection<T>;\n        static all<T>(promises:Promise<T>[]):Promise<T[]>;\n    }\n}\n\ndeclare module "bluebird" {\n    export = bluebird;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

尽管我通常喜欢在定义类型时使用接口,如 #2 所示:

\n\n
declare module bluebird {\n    export interface PromiseInspection<T> {\n        // ...\n    }\n    export interface Promise<T> {\n        constructor<T>();\n        inspect():PromiseInspection<T>;\n    }\n    export interface PromiseStatic {\n        new<T>();\n        all<T>(promises:Promise<T>[]):Promise<T[]>;\n    }\n}\n\ndeclare module "bluebird" {\n    export = bluebird;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果失败,您是否尝试过使用另一个承诺库作为打字的基础?你可以做得比看更糟糕https://github.com/borisyankov/DefinitelyTyped/blob/master/q/Qdts更糟糕

\n\n

粗略地说,它们看起来有点像这样:

\n\n
declare function Q<T>(promise: Q.IPromise<T>): Q.Promise<T>;\ndeclare function Q<T>(promise: JQueryPromise<T>): Q.Promise<T>;\ndeclare function Q<T>(value: T): Q.Promise<T>;\n\ndeclare module Q {\n    //\xe2\x80\xa6 functions etc in here\n}\n\ndeclare module "q" {\n    export = Q;\n}\n
Run Code Online (Sandbox Code Playgroud)\n