Jac*_*cks 5 module node.js typescript
我想达到什么目的
我正在尝试在 TypeScript 中创建一个模块,该模块将包含所需类的每个导出。事实上,真正困扰我的是import
在我的类中拥有所有相对的语句,这并不是进一步维护的最佳方式。我只想使用绝对路径。
一旦被转译,具有绝对路径的类(在生成的 JavaScript 中)有错误的路径(因为它们没有被转换为相对路径,当与tsconfig.json
>outDir
选项结合使用时甚至更糟)。
示例用法
让我们以下面的项目层次结构为例
root
|- helpers
|- MyHelper.ts
|- AnotherHelper.ts
|- calculators
|- MyCalc.ts
|- parsers
|- XmlParser.ts
|- JsonParser.ts
|- index.ts // currently holding export statements
Run Code Online (Sandbox Code Playgroud)
我想做的事
我想要一个这样的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
}
Run Code Online (Sandbox Code Playgroud)
那么我可以执行以下操作:
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 ...
}
}
Run Code Online (Sandbox Code Playgroud)
我在很多地方都看到过(在 SO 上,TypeScript 的 github 存储库,...),我并不是唯一一个在导入相对/绝对路径方面苦苦挣扎的人。
我的实际问题是:是否可以创建这样的模块(或机制),以便我可以在顶级容器中定义每个导出,并像使用 NodeJS 模块(如import * as moment from "moment"
)一样导入此容器?
我试过的
第一次尝试
这是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
Run Code Online (Sandbox Code Playgroud)
第二次尝试
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
}
Run Code Online (Sandbox Code Playgroud)
第三、四、N次尝试
试过declare namespace
,export module
等等等等。没有运气。
也试过declare module "IndexModule
,导致报错:环境模块声明中的导入或导出声明无法通过相对模块名引用模块
边注
我不是 NodeJS / 模块 / 命名空间方面的专家,所以我可能不太了解一些东西。如果是这样,如果有人能指出我的误解,我将不胜感激。
配置 :
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"
}
}
Run Code Online (Sandbox Code Playgroud)
我终于得到了我想要的东西。以下是步骤和相关说明。
为了说明问题/解决方案,让我们以这个树状结构为例
root
\- A
\- a1.ts
\- a2.ts
\- B
\- D
\- bd1.ts
\- bd2.ts
\- b1.ts
\- C
\- c1.ts
\- c2.ts
Run Code Online (Sandbox Code Playgroud)
有一个根文件夹,包含其他 3 个文件夹(A、B 和 C):
a1.ts
和a2.ts
)bd1.ts
和bd2.ts
)和一个文件 ( b1.ts
)c1.ts
和c2.ts
)所以现在,如果bd1.ts
需要在 中声明的类a1.ts
,我们目前将执行 ..
import { ClassFromA1 } from "../../A/a1"
Run Code Online (Sandbox Code Playgroud)
..它使用相对路径并且难以维护(IMO)。我们将在接下来的步骤中摆脱它。
index.ts
包含所有导入的index.ts
该文件(我这样命名,您可以选择任何您想要的名称)的目的是将所有需要的类保留在一个文件中。
因此,我们要做的就是在目录中的树状结构顶部创建此文件node_modules
,并导出项目中所需的每个类。这样,我们只需要该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"
Run Code Online (Sandbox Code Playgroud)
现在我们已经得到了这个,之前的导入可以这样完成..
import { ClassFromA1 } from "../../index"
Run Code Online (Sandbox Code Playgroud)
..但这仍然意味着我们使用相对路径,而不是最佳路径。
在项目中设置arootDir
到root
文件夹可以解决这个问题..
import { ClassFromA1 } from "index"
Run Code Online (Sandbox Code Playgroud)
..它有效!但问题发生在转译类上,其中路径在编译后不会解析为相对路径。
这意味着您的a1.js
(编译a1.ts
文件)仍将具有导入集,但可能是错误的,因为它不了解rootDir
.
// a1.js
const index_1 = require("index") // supposed to be in the same package than the current file
Run Code Online (Sandbox Code Playgroud)
node resolution
策略幸运的是,NodeJS 有一个node resolution
可以设置的策略来解析节点模块导入。以下是可以在我们的项目中设置的Node 模块解析策略的非常简短的摘要:
.
、..
或/
=> 开头,则它是相对路径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
,然后我们可以从中导入所需的类,而无需相对/绝对路径。
现在可以通过以下方式进行导入..
// no matter in which file we are
import { ClassFromA1 } from "index";
import { ClassFromBD1 } from "index";
// and so on ..
Run Code Online (Sandbox Code Playgroud)
..并且它工作得很好,VisualStudio 上没有错误,也没有转译的类。欢迎对此解决方案提出任何评论。
干杯!
归档时间: |
|
查看次数: |
1400 次 |
最近记录: |