从打字稿类型定义文件中导出枚举

Posted

技术标签:

【中文标题】从打字稿类型定义文件中导出枚举【英文标题】:exporting enum from typescript type definition file 【发布时间】:2018-11-06 22:51:03 【问题描述】:

我正在为我正在使用的库编写类型定义。库中的一个函数标识了一个整数单击的鼠标按钮:

 //index.d.ts
 export as namespace myLib;
 // activates the library listening for a specific mouse button
 function activate(button : number ) : void 

我引入了一个枚举来使它更好:

//index.d.ts
export as namespace myLib;
export enum MouseButton 
    LEFT = 1,
    MIDDLE = 2,
    RIGHT = 4


export function activate(button : MouseButton ) : void;

现在,当我导入这个函数并使用它时,一切都会编译,但我猜想枚举在浏览器中执行时会被剥离和未定义。错误消息显示Cannot read property 'LEFT' of undefined

因此我像这样重新排列文件:

//MouseButton.ts
export enum MouseButton 
    LEFT = 1,
    MIDDLE = 2,
    RIGHT = 4


//index.d.ts
export as namespace myLib;
import MouseButton from MouseButton;
export MouseButton from MouseButton;
export function activate(button : MouseButton ) : void;

现在我可以import MouseButton from "myLib/MouseButton"; import * as myLib from "myLib"。但这需要两次导入。引用 myLib.MouseButton 仍然可以编译但不会运行。

有没有办法通过myLib 导入和引用MouseButton 枚举,通过import * as myLib 语句导入?我不仅在寻找解释如何做的答案,而且在寻找解释为什么我的解决方案不起作用或为什么不可能的答案。对解释问题所在的资源提示也表示赞赏

PS:我也尝试了这里建议的语法re-export Typescript enum from namespace?,但这也没有用。

PPS:有问题的模块是 Angular 6 项目中使用的基石项目 (https://github.com/cornerstonejs/cornerstone) 中的 UMD 模块。

【问题讨论】:

发生错误Cannot read property 'LEFT' of undefined的源代码是什么? 此代码是 Angular 项目的一部分(抱歉没有提及)。在执行浏览器的控制台中抛出错误信息。 您是否使用枚举MouseButton 作为反向映射:MouseButton[button]?如果没有,我不知道为什么这个纯 TypeScript 的东西会泄漏到 javascript,除非模块的 JaveScript 捆绑问题。 可能是类型定义语法的问题。这取决于 JavaScript 库的类型:什么样的模块:UMD?纯ES6? ...尝试找到一个类似的库以从其定义文件中获得灵感。如果没有这个库和它的用法(即更多的代码),就很难解释这个问题。 不。我对 MouseButton 的使用如下:myLib.activate(MouseButton.LEFT);(带有两个导入版本)。但我希望它是 myLib.activate(myLib.MouseButton.LEFT)`。 “泄漏”是什么意思?是否应该将其编译掉并替换为枚举值? 【参考方案1】:

(完成 t.animal 自己的答案)

声明文件很难制作:见长documentation。有时查看现有的 .d.ts 文件会有所帮助。

关于enum,将它们声明为const enum 是一种简洁明了的方法。它是 例如,为 jquery 做了什么,请参阅 @types/jquery/index.d.ts 的 MouseKey。这很方便,因为标准枚举在 JavaScript 中编译为数组,而 const enum 成员直接编译为值;见TypeScript Playground。

【讨论】:

如何重新导出? @Jose:我不明白你的问题。也许它应该有自己的全栈溢出问题。【参考方案2】:

在上面Romain Denau's comment 的帮助下解决了这个问题。它把我推向了正确的方向:typescript 编译器从枚举生成什么代码(参见https://www.typescriptlang.org/docs/handbook/enums.html#enums-at-runtime)?声明枚举 const 允许打字稿编译器将标识符与相应的值完全交换,有效地内联它。不再将枚举泄漏到生产代码中。谢谢!

//index.d.ts
export as namespace myLib;

export const enum MouseButton 
    LEFT = 1,
    MIDDLE = 2,
    RIGHT = 4


export function activate(button : MouseButton ) : void;

【讨论】:

"typescript 编译器从枚举定义中生成什么代码?" - 这个。【参考方案3】:

从我对该主题的简短研究中,我注意到使用 export enum const 从类型定义文件中导出枚举是一个坏主意。由于您必须启用 --isolatedModules 标志,这在 create-react-app 中甚至是不可能的,它可能会变得混乱。

相反,我自己在shared.d.ts 文件中使用了正常语法:

  export enum EReviewStatus 
    PENDING = 'PENDING',
    SENT = 'SENT'
  

然后我有一个.js 文件,它被导入到package.json 主块中,例如:

"main": "shared.js",

我在哪里(使用 CommonJS 导出使其在 Node.js 和前端兼容):

module.exports.EReviewStatus = 
  PENDING: 'PENDING',
  SENT: 'SENT'

哪个有效,我认为更好的做法,因为现在您的代码明显与类型分开。

【讨论】:

我没有得到 shared.js 文件部分。你能更准确地说明你做了什么吗?我处于无法禁用 --isolatedModules 的情况,而您的解决方案将挽救我的生命 @Devz 所以我有两个文件:shared.d.ts 和 shared.js(名称是任意的)。它们是使用“types”:“shared.d.ts”和“main”:“shared.js”从 package.json 导入的。我不知道我还能怎么解释。我更新了我的解决方案以使用 CommonJS,因为没有它我无法从我的 Node.js 后端导入 js(而且我不想编译它)。 是的,尝试使用路径、复合和引用的效果不如此选项。 这不是 DRY。为了使它干燥,你可以有一个shared.ts 并从中生成.js.d.ts。或者干脆把整个项目写成 TS。

以上是关于从打字稿类型定义文件中导出枚举的主要内容,如果未能解决你的问题,请参考以下文章

如何从打字稿文件中导出 React 组件

打字稿:要求枚举中的所有键都是有效类型

要求语句不是导入语句的一部分。eslint@typescript-eslint/no-var-需要从存储中导入打字稿

从类型联合定义打字稿函数签名[重复]

打字稿从元组/数组值派生联合类型

如何在 Angular 2 中包含打字稿自定义类型定义?