编写.d.ts文件以便与JavaScript和TypeScript共享常量?

编写.d.ts文件以便与JavaScript和TypeScript共享常量?,javascript,node.js,typescript,types,visual-studio-code,Javascript,Node.js,Typescript,Types,Visual Studio Code,我正在做一个node.js项目,由于历史原因,它同时涉及TypeScript和JavaScript。我想设置一些可以在两种语言中使用的项目范围常量。显而易见:编写一个包含常量的.js文件,以及一个包含TypeScript使用类型的.d.ts文件。但是没有:我花了几个小时来解决这个问题(还有RTFMing),结果一事无成 这是我第一次尝试常量文件: // constants.js const MY_CONST_1 = 1; exports.MY_CONST_1 = MY_CONST_1; 。。。

我正在做一个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;
否:
错误TS2307:找不到模块“./constants”。
因此,必须在与
constants.js
文件相同的目录中编写一个
constants.d.ts
文件,对吗?听起来很容易,但六次不同的尝试都取得了成功。无论我做什么,Typescript都会抱怨
错误TS2306:File'/Users/griscom/Documents/Work/test/constants.d.ts'不是模块

那么,一个成功的
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:
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
export const MY_CONST_1: number;
您可以编写一个如下所示的
constants.d.ts
文件:

// constants.js
export const MY_CONST_1 = 1;
// constants.d.ts
export const MY_CONST_1: number;
在以前的尝试中,您关闭的地方是使用声明
模块
,该声明用于声明外部模块的类型(如来自
节点的模块
)。在这种情况下,只需将
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
存在的原因之一,因为它避免了此类泄漏

export const MyConst =1;

通常远离模块,因为这与inports中模块的含义不一致。取而代之的是使用“名称空间”,它非常类似于具有静态成员的类。意思是你可能会做(在电话上,不能尝试):

但最后,尽量避免在额外的名称空间和类等中包装东西,因为导入语法是模块。此外,它还使您的代码树形化。

另一个选项:使用。事实上,您的常量是全局的,即由于缺少
export
关键字,因此未在模块中定义:

import./constants'


与另一个响应中提到的
allowJs
编译器选项结合使用。

好主意,但是我项目中的所有其他JavaScript文件都会触发错误:“无法写入文件XXXX,因为它会覆盖输入文件”。是的,您需要将源文件与输出文件分开。JS源文件将以最小的转换进行复制(例如,只有ES6到ES5语法)。为什么不呢?或者,编写
.d.ts
文件应该可以,您尝试过什么?这是一个很大的现有项目,添加此功能的好处将被更改生成过程的复杂性所抵消。关于
.d.ts
文件,我在网上找到了很多示例,但编译器一直在含糊其辞地抱怨。我知道这种感觉,但根据我的经验,这通常更像是一个心理障碍你能把你在问题中尝试过的
.d.ts
东西贴出来吗?