使用 baseUrl 导入模块时如何让 tsc 解析绝对路径?

How to get tsc to Resolve Absolute Paths when Importing Modules using baseUrl?

考虑一个具有以下目录结构的简单打字稿项目:

|   package.json
|   tsconfig.json
|               
\---src
    |   app.ts
    |   
    \---foobar
            Foo.ts
            Bar.ts

tsconfig.json 已配置为 ./src/baseUrl

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "outDir": "./dist/",
        "baseUrl": "./src/"
    },
    "include": [
        "./src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

现在假设我们要在 Bar.ts 中导入 Foo。我的理解是,通过设置baseUrl,我们现在可以使用绝对路径导入模块

import { Foo } from 'foobar/Foo'

相对于相对路径

import { Foo } from './Foo'

如果我的理解是正确的,打字稿编译器在编译Bar.ts时应该能够自动解析foobar/Foo./Foo

import { Foo } from 'foobar/Foo';

export class Bar {
  foo: Foo;

  constructor(num: number) {
    this.foo = new Foo(num);
  }
}

运行 tsc 编译没有错误。然而,当我们实际查看编译后的 Bar.js 时,我们会发现路径没有被正确解析,如果我们要这样做,这会给我们一个 Cannot find module 错误运行它。

"use strict";
const Foo_1 = require("foobar/Foo");
class Bar {
    constructor(num) {
        this.foo = new Foo_1.Foo(num);
    }
}
exports.Bar = Bar;

所以我的问题是:在使用baseUrl导入模块时,如何让tsc正确解析绝对路径?或者如果这不是可以做到的,那么baseUrl的目的是什么?

问题是你的模块加载器不知道如何找到给定绝对路径的模块 foobar/Foo

TypeScript 编译器 (tsc) 正在正确解析模块路径,否则您会遇到编译错误。但它相信你会适当地配置你的模块加载器。

例如,来自 documentation for RequireJS

Supported configuration options:

baseUrl: the root path to use for all module lookups.

TypeScript documentation 稍微解释了为什么您可能需要 baseUrl:

Using a baseUrl is a common practice in applications using AMD module loaders where modules are “deployed” to a single folder at run-time. The sources of these modules can live in different directories, but a build script will put them all together.

tsc 无法将路径转换为相对路径,尽管您配置了 baseUrlpathspaths 仅在您在编辑器中编码以检查代码时有用。 如果你想让它工作,你可以使用 ts-node 和 tsconfig-paths 模块:

$ yarn add ts-node tsconfig-paths --dev

和运行这个脚本

"start": "ts-node -r tsconfig-paths/register app.ts"

然后你就可以得到正确的表现。

答案来自@DenisPshenov 在其中一个答案中的评论。它被埋没了,所以我会在这里提供...

使用 NODE_PATH 环境变量告诉 Node 基础 url 在哪里,以便它可以解析绝对路径:

Linux / macOS

NODE_PATH=dist/ node ./dist/index.js

Windows Powershell

$env:NODE_PATH="dist/"
node ./dist/index.js

您可以使用 tsconfig 的 path:

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
        "app/*": ["app/*"],
        "config/*": ["app/_config/*"],
        "environment/*": ["environments/*"],
        "shared/*": ["app/_shared/*"],
        "helpers/*": ["helpers/*"],
        "tests/*": ["tests/*"]
    },
}

In this case, you can tell the TypeScript file resolver to support a number of custom prefixes to find code. This pattern can be used to avoid long relative paths within your codebase.

https://www.typescriptlang.org/tsconfig