如何在声明文件的命名空间中键入循环引用?

How do you type a circular reference in a namespace in a declaration file?

我正在尝试为 DefinitelyTyped 项目键入一个 UMD 模块(我不拥有它,所以我无法更改它),它具有类似的东西(当然具有实际功能):

function getModule() {
    function fn1() {}
    function fn2() {}

    fn1.fn2 = fn2;
    return fn1.fn1 = fn1;
}

if (typeof define === "function" && define.amd) {
    define(getModule());
} else if (typeof module !== "undefined" && module.exports) { 
    module.exports = getModule();
} else {
    this.moduleName = getModule();
}

使用 the module-function.d.ts 模板,到目前为止我有这个:

export as namespace moduleName;

export = fn1;

declare function fn1(): void;

declare namespace fn1 {
    function fn2(): void;
}

然后我使用 dts-gen 为我生成了一个 .d.ts 文件,试图找出如何在 fn1 命名空间中再次声明 fn1 函数,并且得到这个:

/** Declaration file generated by dts-gen */

export = moduleName;

declare function moduleName(): void;

declare namespace moduleName {
    // Circular reference from moduleName
    const fn1: any;

    function fn2(): void;
}

但是,当我尝试在以下代码中组合两者时,出现错误 'fn1' is referenced directly or indirectly in its own type annotation.

export as namespace moduleName;

export = fn1;

declare function fn1(): void;

declare namespace fn1 {
    function fn2(): void;
    const fn1: any;
}

我不想执行以下操作,因为那样的话它不代表您可以执行 require('moduleName').fn1.fn1.fn1.fn2(或任意数量的 fn1s.

export = moduleName;

declare function moduleName(): void;

declare namespace moduleName {
    function fn1(): void;
    function fn2(): void;
}

我该如何输入这个模块?

可以使用一个接口来准确表示递归类型:

export = fn1;

declare const fn1: Fn1

interface Fn1 {
  // The call signature of fn1
  (): void
  // The circular reference
  fn1: Fn1
  // Other functions
  fn2: () => void
}