在代码中如何判断使用 ts-node 运行的话就不调用 `register()`?

在代码中有部分是加载 TypeScript 类型的配置文件的代码,大概如下

export function loadTypeScriptConfig(configPath: string) {
  // noinspection TypeScriptValidateJSTypes
  require('ts-node').register()
  return require(configPath)
}

但如果使用 ts-node 运行这段代码,则会发生错误,看了一下 ts-node issue 里说加载了两次。那么,是否有判断是否使用 ts-node 运行的方法,以此避免这个问题?

ts-node 相关 issue:https://github.com/TypeStrong...
阅读 4.2k
2 个回答

使用 ts-node 加载 TypeScript 配置文件

export function loadTypeScriptConfig(configPath: string) {
  // noinspection TypeScriptValidateJSTypes
  require('ts-node').register()
  return require(configPath)
}

单元测试

import * as path from 'path'
import { loadTypeScriptConfig } from '../loadTypeScriptConfig'

it('测试 loadTypeScriptConfig', () => {
  const start = Date.now()
  const config = loadTypeScriptConfig(
    path.resolve(__dirname, './test.config.ts'),
  )
  const end = Date.now()
  console.log('config: ', JSON.stringify(config), ', ms: ', end - start)
})
参考:https://inspirnathan.com/post...

问题

在使用 ts-node 加载的配置文件中包含第三方依赖时,会出现以下错误

TSError: ⨯ Unable to compile TypeScript:
src/test.config.ts:5:5 - error TS7022: '__importDefault' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.

5 var __importDefault = (this && this.__importDefault) || function (mod) {
      ~~~~~~~~~~~~~~~
src/test.config.ts:5:67 - error TS7006: Parameter 'mod' implicitly has an 'any' type.

5 var __importDefault = (this && this.__importDefault) || function (mod) {

解决方案

  1. 在代码中如何判断使用 ts-node 运行的话就不调用 register()
    使用 require.extensions 判断是否包含 ts 加载器,不包含再注册 ts-node

    require.extensions
  2. 使用 "importHelpers": true 选项

    1. 添加依赖 tslib
    2. 修改配置
    {
      "ts-node": {
        "compilerOptions": {
          "module": "CommonJS",
          "importHelpers": true
        }
      }
    }
  3. 判断环境变量是否包含 ts-node process.argv[0].includes('ts-node')
对比require.extensionsimportHelpersprocess.argv
优点没有额外依赖不需要使用过时的 API没有额外依赖
缺点需要用户配置需要用户配置需要用户配置
使用过时的 API额外依赖 tslib有点 hack 的方法
判断不准确,例如路径中包含 ts-node

可以通过 process.argv 的第一个参数判断

const isTsNode = process.argv[0].endsWith('ts-node');