使用 esm 时,带有 tsconfig-paths 的 ts-node 将不起作用

UnL*_*oCo 19 alias typescript tsconfig ts-node

我不明白为什么ts-node在启用 esm 时无法解析别名

我做了一个小项目试图尽可能地隔离问题

package.json

{
  "type": "module"
}
Run Code Online (Sandbox Code Playgroud)

tsconfig.json

{
  "compilerOptions": {
    "module": "es2020",                                
    "baseUrl": "./",                                  
    "paths": {
      "$lib/*": [
        "src/lib/*"
      ]
    },
  },
  "ts-node": {
    "esm": true
  }
}
Run Code Online (Sandbox Code Playgroud)

test.ts

import { testFn } from "$lib/module"

testFn()
Run Code Online (Sandbox Code Playgroud)

lib/module.ts

export function testFn () {
  console.log("Test function")
}
Run Code Online (Sandbox Code Playgroud)

命令

import { testFn } from "$lib/module"

testFn()
Run Code Online (Sandbox Code Playgroud)

这是一个最小的回购协议

kol*_*ein 8

解决方案来自:https://github.com/TypeStrong/ts-node/discussions/1450#discussion-3563207

目前,ESM 加载器不处理 TypeScript 路径映射。为了使其工作,您可以使用以下自定义加载程序:

// loader.js
import {
  resolve as resolveTs,
  getFormat,
  transformSource,
  load,
} from "ts-node/esm";
import * as tsConfigPaths from "tsconfig-paths"

export { getFormat, transformSource, load };

const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig()
const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths)

export function resolve(specifier, context, defaultResolver) {
  const mappedSpecifier = matchPath(specifier)
  if (mappedSpecifier) {
    specifier = `${mappedSpecifier}.js`
  }
  return resolveTs(specifier, context, defaultResolver);
}
Run Code Online (Sandbox Code Playgroud)

然后使用加载器: node --loader loader.js index.ts

警告:这仅适用于没有扩展名的模块说明符。例如,导入/foo/bar有效,但导入/foo/bar.js和导入/foo/bar.ts无效。

还记得安装这些软件包:

"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.2",
Run Code Online (Sandbox Code Playgroud)

更新日期:2023 年 9 月 11 日

新的加载器将自动解析index.(js|ts)

import { resolve as resolveTs } from 'ts-node/esm'
import * as tsConfigPaths from 'tsconfig-paths'
import { pathToFileURL } from 'url'

const { absoluteBaseUrl, paths } = tsConfigPaths.loadConfig()
const matchPath = tsConfigPaths.createMatchPath(absoluteBaseUrl, paths)

export function resolve (specifier, ctx, defaultResolve) {
  const match = matchPath(specifier)
  return match
    ? resolveTs(pathToFileURL(`${match}`).href, ctx, defaultResolve)
    : resolveTs(specifier, ctx, defaultResolve)
}

export { load, transformSource } from 'ts-node/esm'
Run Code Online (Sandbox Code Playgroud)

例子:

Path: /src/modules/order/index.ts
Resolve: import orderModule from '@/modules/order';
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记从“ts-node/esm”重新导出“load”,否则你会得到“TypeError [ERR_UNKNOWN_FILE_EXTENSION]:未知文件扩展名“.ts”” (4认同)