如何在模块声明中重新导出命名空间定义

use*_*543 5 types typescript lodash typescript-typings

首先,我想了解为什么一些 TypeScript 定义文件以两种形式给出(我将尝试通过lodash示例来展示这一点)。

第一个是“基于命名空间”(来自@types/lodash定义):

export = _;
export as namespace _;
declare var _: _.LoDashStatic;
declare namespace {
    (...)
}
Run Code Online (Sandbox Code Playgroud)

第二个是“基于模块”(来自typings模块定义):

declare module 'lodash' {
    var _: _.LoDashStatic;
    namespace _ {
        (...)
    }
    export = _;
}
Run Code Online (Sandbox Code Playgroud)

同一个库的两个定义源显示了不同的方法。这里的权衡是什么,为什么一些来自@types/...源代码的类型在第二个中优先考虑?

我在将“基于命名空间”的定义与位于我的项目范围之外的共享代码一起使用时遇到了一些问题,因此我更喜欢“基于模块”的定义。好了,第二步来了。我想标准化这些定义并且只使用@types/...源,但是当我得到“基于命名空间”的定义(比如lodash)时,我想编写一些自定义定义(尽可能短),它将在“基于模块”中重新导出该命名空间道路。

我试过这样的事情:

declare module "lodash" {
    import * as x from "lodash";

    var _: x.LoDashStatic;
    namespace _ {}
    export = _;
}
Run Code Online (Sandbox Code Playgroud)

这当然不起作用(除了不再有cannot find module...错误),但我认为几乎显示了我在这里想要完成的工作。我的目标是使用声明的命名空间@types/lodash/index.d.tscustom_typings/lodash.d.ts使用模块声明将其导出到不同的文件(如)。

总结一下,出现了两个问题:

  1. 为什么定义以两种不同的方式构建?
  2. 如何简单地将一种方法转换为另一种方法?

小智 0

经过这么多时间寻找解决方案,我终于成功了!

/** index.d.ts */
import './models';

// tslint:disable-next-line:no-namespace
declare namespace MyLib {
    export interface A {
        // ...
    }

    // ...
}


/** extra.d.ts */
// tslint:disable-next-line:no-module
declare module './index' {
    export interface B {
        // ...
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后,消费者可以将A&B作为MyLib命名空间的一部分进行访问。此外,您可以正确访问B中定义的命名空间的范围index.d.ts

我同意语法不太好,但它确实有效。lodash 类型中使用了类似的方法:

虽然在上面的 POC 中我更喜欢使用 es6import语法,但 lodash 类型使用/// <reference. 这两个选项都有效,因此由您决定。