编写 .d.ts 文件以便我可以与 JavaScript 和 TypeScript 共享常量?
Posted
技术标签:
【中文标题】编写 .d.ts 文件以便我可以与 JavaScript 和 TypeScript 共享常量?【英文标题】:Writing .d.ts file so I can share constants with JavaScript and TypeScript? 【发布时间】:2018-06-26 14:46:15 【问题描述】:我正在开发一个 node.js 项目,由于历史原因,该项目同时涉及 TypeScript 和 javascript。我想设置一些可以在两种语言中使用的项目范围的常量。显而易见:编写一个带有常量的.js
文件,以及一个包含TypeScript 使用类型的.d.ts
文件。但是没有:解决这个问题(和 RTFMing)的几个小时让我无处可去。
这是我对常量文件的第一次尝试:
// constants.js
const MY_CONST_1 = 1;
exports.MY_CONST_1 = MY_CONST_1;
... 以及使用它的 JavaScript:
// consumer.js
let constants = require('./constants');
let one = constants.MY_CONST_1;
效果很好,但是当我在 TypeScript 中尝试显而易见的时候:
// consumer.ts
import * as constants from './constants';
let one: number = constants.MY_CONST_1;
不:error TS2307: Cannot find module './constants'.
所以,必须在与constants.js
文件相同的目录中编写一个constants.d.ts
文件,对吧?听起来很容易,但六种不同的尝试已经产生了准确的结果。不管我做什么,Typescript 都会抱怨error TS2306: File '/Users/griscom/Documents/Work/test/constants.d.ts' is not a module
。
那么,一个成功的constants.d.ts
文件应该是什么样的?或者,如果我必须在 constants.js
中进行更改才能使这一切正常工作,它们会是什么?
附:这是我的tsconfig.json
文件:
"compilerOptions":
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"noImplicitReturns": true
(这似乎是一个简单而明显的需求;令人沮丧的是这个过程是多么不透明。)
【问题讨论】:
【参考方案1】:选项 1:allowJs
尝试使用编译器选项allowJs: true
。这将允许您从 ./constants
进行原始导入,即使它是 .js
文件,也无需创建单独的 .d.ts
文件。 TypeScript 将理解来自 .js
文件的可推断类型,例如,您将针对 MY_CONST_1
作为数字进行类型检查。
正如您在评论中所说,这需要将源文件与输出文件分开,因为它不能在与 JS 源文件相同的位置输出 JS 文件。
选项2:constants.d.ts
声明文件
鉴于您的源文件如下所示:
// constants.js
export const MY_CONST_1 = 1;
您可以编写一个如下所示的constants.d.ts
文件:
// constants.d.ts
export const MY_CONST_1: number;
您之前的尝试中没有使用声明module
,它用于声明外部模块的类型(例如来自node_modules
)。在这种情况下,只需将constants.d.ts
文件与constants.js
放在同一目录中并使用export
将告诉TS 它是一个导出该值的JS 模块:
import MY_CONST_1 from "./constants";
import * as constants from "./constants";
需要牢记的重要一点是.d.ts
文件不会与.js
文件进行核对以确保它实际上是正确的,这取决于您。因此,如果您对.js
文件进行更改,您必须确保相应地正确更新.d.ts
文件。编译错误或缺少编译错误并不意味着它是正确的或不正确的。这是allowJs
存在的原因之一,因为它避免了此类泄漏。
【讨论】:
好主意,但是我项目中的所有其他 JavaScript 文件都会触发错误:“无法写入文件 XXXX,因为它会覆盖输入文件”。 是的,您需要将源文件与输出文件分开。 JS 源文件将以最小的转换被复制(例如,仅 ES6 到 ES5 语法)。 为什么不呢?或者写一个.d.ts
文件应该可以,你试过什么?
这是一个大型的现有项目,添加此功能的好处将被更改构建过程的复杂性所抵消。关于.d.ts
文件,我尝试了一些我在网上找到的示例,但编译器一直在抱怨。
我知道这种感觉,但根据我的经验,这通常更像是一种心理障碍。 :) 您可以发布您在问题中尝试过的.d.ts
内容吗?【参考方案2】:
export const MyConst =1;
或者
export class MyGroup
static MyConst: number
通常不要使用模块,因为这与 inports 中模块的含义不兼容。而是使用与具有静态成员的类非常相似的“命名空间”。这意味着您可能会这样做(在手机上但无法尝试):
export namespace MyNamespace
export const MyConst = 1;
但最后尽量避免将东西包装在额外的命名空间和类等中,因为导入语法是模块。它还使您的代码可摇晃。
【讨论】:
michelenasti.com/2019/01/23/…【参考方案3】:另一种选择:使用import for side effects only。实际上,您的常量是全局的,即由于缺少 export
关键字而未在模块中定义:
import './constants';
与另一个回复中提到的allowJs
编译器选项结合使用。
【讨论】:
以上是关于编写 .d.ts 文件以便我可以与 JavaScript 和 TypeScript 共享常量?的主要内容,如果未能解决你的问题,请参考以下文章