当前位置 : 主页 > 网页制作 > Nodejs >

node.js – 在TypeScript中创建包含所有导出的模块

来源:互联网 收集:自由互联 发布时间:2021-06-16
我想要实现的目标是什么 我正在尝试在TypeScript中创建一个模块,该模块将包含所需的每个类的导出.事实上,让我感到困扰的是我的班级中的导入语句都是相对的,这实际上不是进一步维护
我想要实现的目标是什么

我正在尝试在TypeScript中创建一个模块,该模块将包含所需的每个类的导出.事实上,让我感到困扰的是我的班级中的导入语句都是相对的,这实际上不是进一步维护的最佳方式.我想只使用绝对路径.

一旦被转换,具有绝对路径的类(在生成的JavaScript中)具有错误的路径(因为它们没有被转换为相对路径,并且当与tsconfig.json> outDir选项一起使用时甚至更糟).

用法示例

让我们从以下项目层次结构开始作为示例

root
|- helpers
   |- MyHelper.ts
   |- AnotherHelper.ts
|- calculators
   |- MyCalc.ts
|- parsers
   |- XmlParser.ts
   |- JsonParser.ts
|- index.ts // currently holding export statements

我想做的事

我想要一个这样的index.ts文件:

// a top-level module, resolved like the `node` strategy of NodeJS module resolution
export module IndexModule {
    export { MyHelper } from "./helpers/MyHelper";
    export { AnotherHelper } from "./helpers/AnotherHelper";
    // do the same for every class in my project
}

那么我可以做以下事情:

import { JsonParser } from "IndexModule"; // no relative nor absolute path

export class MyHelper {
    public constructor(input: any){
       var result: any = new JsonParser().parse(input);
       // work with result ...
    }
}

我已经在许多地方看到过(在这里,SO,the github repo of TypeScript,……),我不是唯一一个与进口的相对/绝对路径挣扎的人.

我的实际问题是:是否可以创建这样的模块(或机制),以便我可以在顶部容器中定义每个导出,并导入此容器,就像我使用NodeJS模块一样(如导入*作为“时刻”的时刻) )?

我尝试了什么

第一次尝试

这是我实际拥有的index.ts文件:

// index.ts is in the root directory of the project, it accesses classes with relative paths (but here, management is quite easy)
export { Constants } from "./helpers/Constants";
export { ConstraintCalculatorHelper } from "./helpers/ConstraintCalculatorHelper";
export { MomentHelper } from "./helpers/MomentHelper";
export { Formatter, OutputFormatterHelper } from "./helpers/OutputFormatterHelper";
// ... doing this for each class I have in my project

第二次尝试

declare module IndexModule {
    export { Constants } from "./helpers/Constants";
    export { ConstraintCalculatorHelper } from "./helpers/ConstraintCalculatorHelper";
    export { MomentHelper } from "./helpers/MomentHelper";
    export { Formatter, OutputFormatterHelper } from "./helpers/OutputFormatterHelper";
    // error : Export declarations are not permitted in a namespace
}

第三,第四,第N次尝试

试图声明命名空间,导出模块等等.没有运气.

试图声明模块“IndexModule也导致错误:环境模块声明中的导入或导出声明不能通过相关模块名称引用模块

边注

我不是NodeJS / Modules / Namespaces的专家,所以我可能还没有理解.如果是这样,如果有人能够指出我误解的内容,我将不胜感激.

Relevant link here that shows the actual problem.

配置:

> NodeJS v7.2
> TypeScript v2.2

tsconfig.json:

{
  "compileOnSave": true,
  "compilerOptions": {
    "removeComments": false,
    "sourceMap": true,
    "module": "commonjs",
    "target": "es6",
    "noImplicitAny": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "outDir": "./bin/LongiCalc"
  }
}
我终于设法得到了我想要的东西.以下是步骤和解释.

1.架构示例

为了说明问题/解决方案,让我们以此树状为例

root
  \- A
     \- a1.ts
     \- a2.ts
  \- B
     \- D
        \- bd1.ts
        \- bd2.ts
     \- b1.ts
  \- C
     \- c1.ts
     \- c2.ts

有一个根文件夹,包含3个其他文件夹(A,B和C):

> A包含两个文件(a1.ts和a2.ts)
> B包含一个包含两个文件的文件夹(D,带有bd1.ts和bd2.ts)和一个文件(b1.ts)
> C包含两个文件(c1.ts和c2.ts)

所以现在,如果bd1.ts需要在a1.ts中声明的类,我们现在会做..

import { ClassFromA1 } from "../../A/a1"

..使用相对路径并且难以维护(IMO).我们将在接下来的步骤中摆脱它.

2.使用所有导入创建index.ts

index.ts文件的目的(我这样命名,你可以选择你想要的任何名称)是将所有需要的类保存在一个文件中.

所以我们要做的是在node_modules目录中的arborescence顶部创建这个文件,并导出我们项目中需要的每个类.这样,我们只需要index.ts文件来检索我们想要的类.

以下是内容:

// current position : root/node_modules/index.ts
export { ClassFromA1 }  from "./A/a1.ts"
export { ClassFromA2 }  from "./A/a2.ts"
export { ClassFromBD1 } from "./B/D/bd1.ts"
export { ClassFromBD2 } from "./B/D/bd2.ts"
export { ClassFromB1 }  from "./B/b1.ts"
export { ClassFromC1 }  from "./C/c1.ts"
export { ClassFromC2 }  from "./C/c2.ts"

现在我们已经得到了这个,之前的导入可以通过这种方式完成.

import { ClassFromA1 } from "../../index"

..但这仍然暗示我们使用相对路径,而不是最优路径.

在项目中设置rootDir到根文件夹可以解决这个问题.

import { ClassFromA1 } from "index"

..它的确有效!但问题发生在已编译的类中,其中路径在编译后不会被解析为相对路径.

这意味着你的a1.js(已编译的a1.ts文件)仍然会按原样设置导入,但可能会出错,因为它不知道rootDir.

// a1.js
const index_1 = require("index") // supposed to be in the same package than the current file

3.选择节点解析策略

幸运的是,NodeJS具有可以设置为解析节点模块导入的节点解析策略.这是一个可以在我们的项目中设置的really brief summary of the Node module resolution strategy:

>检查导入路径
>如果导入路径以.,..或/ =>开头它是相对的
>如果导入路径以name =>开头它是一个节点模块(这很重要)

NodeJS中模块的解析如下(始终从bs1.ts开始):

>检查root / B / D / node_modules / index.ts是否存在>没有
>检查root / B / node_modules / index.ts是否存在>没有
>检查root / node_modules / index.ts是否存在>是的!

我们在这里做的是,我们欺骗Typescript认为index.ts是一个NodeJS模块,它必须作为一个解析.

它将使用上面描述的模式(并在链接中)来检索index.ts,然后我们可以导入所需的类而不使用相对/绝对路径.

4.按我们的意愿进口

现在可以通过以下方式进口…

// no matter in which file we are
import { ClassFromA1 } from "index";
import { ClassFromBD1 } from "index";
// and so on ..

..它工作得很好,VisualStudio没有错误,也没有编译过.欢迎任何关于此解决方案的评论.

干杯!

网友评论