TypeScript导入路径别名

92

我目前正在开发一个TypeScript应用程序,其中包括多个使用TypeScript编写的Node模块,这些模块被安装到node_modules目录中。

在继续之前,我要注意一下,我正在使用TypeScript 2.0,如果需要,我也不排斥使用2.1开发版本。我只是想让这个工作起来。

每个Node模块的结构大致如下:

dist/
    es2015/
        index.js
        utils/
            Calculator.js
            Calculator.d.ts
            Date.js
            Date.d.ts
            Flatpack.js
            Flatpack.d.ts
src/
    index.ts
    utils/
        Calculator.ts
        Date.ts
        Flatpack.ts

dist文件夹是生成的源代码,该路径通过在我的tsconfig.json文件中配置outDir来配置。我还将package.json中的main属性配置为dist/es2015/index.js

需要注意的重要事项:

  • 在我的项目中,我使用了nodemoduleResolution类型。
  • 我正在使用TypeScript 2.0
  • 我不是在问如何从包内导入文件。我通过Npm安装程序包,然后在使用此模块的应用程序中通过packagename/进行导入。

现在来谈谈我的问题/问题所在。当从此模块中导入文件时,我想能够这样做:

import {Sin, Cos, Tan} from "common-utils/utils/Calculator";

然而,该文件无法解析到 dist/es2015/utils 目录。理想情况下,我希望我的引用从这个特定的 dist 文件夹解析,而不是从根目录解析,这似乎是正在发生的事情。

为了使其正常工作,上述导入需要编写成以下形式:

import {Sin, Cos, Tan} from "common-utils/dist/es2015/utils/Calculator";

然而,每次写dist/es2015都不是理想的解决方法,这只会使某些导入看起来非常冗长。我是否可以配置我的模块以解析到dist/es2015目录? 我不想在我的项目中放置覆盖,理想情况下每个模块都会指定文件的解析位置。

如果您仍然不确定我的要求(如果这很令人困惑,我很抱歉),在使用Jspm创建插件/模块时,您可以在模块的package.json中指定类似以下内容:

  "jspm": {
    "registry": "npm",
    "jspmPackage": true,
    "main": "my-module",
    "format": "amd",
    "directories": {
      "dist": "dist/amd"
    },

我正在寻找TypeScript中类似的东西(如果有的话)。映射指令,所以当最终用户运行npm install my-cool-package,然后在他们的应用程序中尝试导入某些内容时,默认情况下所有导入都会解析到commonjs目录(上面的示例针对Jspm使用amd,但原理相同)。

这是否可能,还是我误解了什么?我知道一些新的路径映射功能已添加到最新版本中,但几乎没有关于如何使用它们的文档。


2
如果你在 index.ts 中导入了 Calculator.ts,你可以尝试使用 import {Sin,Cos,Tan} from "./utils/Calculator" - irakli khitarishvili
1
如果从包内部导入,这肯定会起作用。然而,我的问题是,这是一个我安装到 node_modules 中的模块,然后使用 from "packagename/" 导入 - 问题在于添加直接路径到 dist 文件夹感觉很混乱,我想将其别名为默认导入位置,但要从模块内部完成,而不是我必须在消费模块的项目中进行配置。 - Dwayne Charrington
如果您添加配置对象,在其中可以添加包名称或文件名,并“构建”您的路径,还可以查看system.js或webpack来执行此任务。 - Aren Hovsepyan
我本来希望能够避免构建任务来使路径逻辑工作。话虽如此,这似乎是大多数CommonJS模块构建的常规做法。 - Dwayne Charrington
2个回答

187

阅读了您的评论后,我意识到我误解了您的问题!如果您想从导入的包的角度控制路径,请将package.jsonmain属性设置为一个正确表示模块对象图的文件。

{
  "main": "common-utils/dist/es2015/index.js"
}

如果您希望从项目的角度控制导入路径,您需要使用TypeScript 2的新路径映射功能来解决模块解析。您可以通过以下方式配置tsconfig.json启用路径映射:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "angular2/*": ["../path/to/angular2/*"],
      "local/*": ["../path/to/local/modules/*"]
    }
  }
}

然后,在你的 TypeScript 文件中,你可以像这样导入模块:

import { bootstrap } from 'angular2/bootstrap';
import { module } from 'local/module';

有关 TypeScript 2 中路径映射功能的更多细节,请参见 此 Github 问题

在您的情况下,我认为以下配置应该可以工作:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "common-utils/utils/*": ["./node_modules/common-utils/dist/es2015/utils/*"]
    }
  }
}

谢谢@faraz。我今天上午会尝试一下。路径配置应该放在我的模块中,而不是项目中,对吧?然后当我引入我的模块时,TypeScript编译器应该能够识别出在这个文件中定义的路径,对吗? - Dwayne Charrington
不,路径配置应该放在您的 TypeScript 项目中,并且应该指向您想要从项目中引用的模块。 - fny
我认为我已经在项目中以类似的方式使其工作了。这是否意味着从模块的角度来看,目前在TypeScript本身中不可能实现我要求做的事情?我很想做上述操作,但是在包本身中定义它,这样在导入时就可以捕获路径别名。Jspm允许包配置路径别名,我希望TypeScript也提供相同的功能,因为告诉用户添加这些路径别名有点麻烦。一个路径匹配模式字符串中是否支持多个通配符? - Dwayne Charrington
啊,我误解了你的问题!我没有意识到你想要从包中直接配置。为什么不在你的 package.json 中设置 main 属性为一个适当的索引文件呢? - fny
谢谢Faraz。我已经接受了你的答案。我希望避免暴露我的导入,所以不想使用index.js文件。我认为我会选择项目配置路线,这些模块都不是公共模块,并且它们都在同一个作用域下,所以我知道作用域始终相同。对于公共模块,基于CommonJS的index.js文件导出所有公共接口肯定是正确的方法。Aurelia Javascript框架采用了这种方法,许多其他CommonJS模块也是如此。再次感谢,你应该得到这个赏金。 - Dwayne Charrington
1
这种方法能让我在TypeScript应用程序中使用import {Date} from 'common-utils/src/utils/Date'并且让tsc将其重写为dist/....吗? - Nicholas Albion

12

如果您正在使用路径,编译TypeScript成纯JavaScript后,您需要将绝对路径改为相对路径才能使其正常工作。

目前最流行的解决方案是 tsconfig-paths

我尝试了它,但对于我的复杂设置而言并没有起作用。 此外,它在运行时解析路径,意味着会增加包大小和解析性能的开销。

因此,我自己写了一个解决方案,tscpaths

总的来说,我认为它更好,因为它在编译时替换路径。这意味着没有运行时依赖或任何性能开销。它非常简单易用,只需要在 package.json 的构建脚本中添加一行即可。

该项目还很年轻,如果您的设置非常复杂,则可能会有一些问题。不过,对于我的设置而言,它完美地运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接