Skip to main content

ts-node

官方文档

基础使用

安装

# Locally in your project.
npm install -D typescript ts-node

# Or globally with TypeScript.
npm install -g typescript ts-node

# Depending on configuration, you may also need these
npm install -D tslib @types/node

基础使用

# Execute a script as `node` + `tsc`.
ts-node script.ts

# Starts a TypeScript REPL.
ts-node

# Execute code with TypeScript.
ts-node -e 'console.log("Hello, world!")'

# Execute, and print, code with TypeScript.
ts-node -p -e '"Hello, world!"'

# Pipe scripts to execute with TypeScript.
echo 'console.log("Hello, world!")' | ts-node

# 等价于 to ts-node --transpileOnly
ts-node-transpile-only script.ts

# 等价于 to ts-node --cwdMode
ts-node-cwd script.ts

# 等价于 to ts-node --esm
ts-node-esm script.ts

增加编译速度

--noEmit

关键配置

官方文档

# https://www.npmjs.com/package/@tsconfig/node16
npm install --save-dev @tsconfig/node16
yarn add --dev @tsconfig/node16

# or
npm install
  • CommonJS 的项目模板
// tsconfig.json
{
"extends": "@tsconfig/node16/tsconfig.json",
"ts-node": {
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "ESNext",
"module": "CommonJS",
"moduleResolution": "node",
"strict": true,
"noEmit": true,
"types": ["./node_modules/@types", "./types"]
}
}
}
  • 适合原生ESNext的项目
// tsconfig.json
"extends": "@tsconfig/node16/tsconfig.json",
"ts-node": {
"esm": true, // 对应 --esm flag,明确当前采用ESModule的方式管理包导入
"experimentalSpecifierResolution": "node", // 如果module为ESNext则需要开启
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"noEmit": true,
"types": ["./node_modules/@types", "./types"]
}
}
}

坑 - 常见错误

throw new ERR_MODULE_NOT_FOUND( Cannot find module

w:\CPS\nodejs\v16.6.2\node_modules\ts-node\dist-raw\node-internal-modules-esm-resolve.js:366 throw new ERR_MODULE_NOT_FOUND( ^ CustomError: Cannot find module 'W:\CPS\MyProject\test\test2' imported from W:\CPS\MyProject\test\test.ts at finalizeResolution (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\dist-raw\node-internal-modules-esm-resolve.js:366:11) at moduleResolve (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\dist-raw\node-internal-modules-esm-resolve.js:801:10) at Object.defaultResolve (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\dist-raw\node-internal-modules-esm-resolve.js:912:11) at w:\CPS\nodejs\v16.6.2\node_modules\ts-node\src\esm.ts:218:35 at entrypointFallback (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\src\esm.ts:168:34) at w:\CPS\nodejs\v16.6.2\node_modules\ts-node\src\esm.ts:217:14 at addShortCircuitFlag (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\src\esm.ts:409:21) at resolve (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\src\esm.ts:197:12) at resolve (w:\CPS\nodejs\v16.6.2\node_modules\ts-node\src\child\child-loader.ts:15:39) at Loader.resolve (node:internal/modules/esm/loader:89:40)

出现场景:

调用ts-node执行ts文件的时候,一些无明确后缀名的模块报错,找不到该模块等等

// 引入的自定义模块没有指定后缀名,因为文件名称是.ts
import { coustom_module } from "./coustomModule"

当前tsconfig.jsonts-node配置为:

{
"ts-node": {
"esm": true,
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node"
}
}
}

当前package.jsontype字段为:module

原因解释:

主要原因跟node的查找包机制有关,node16当前使用esm模式的话需要指定为.mjs文件,而使用CommontJS则使用.cjs文件,想通过不指定后缀名称的方式引入模块,需要开启--experimental-specifier-resolution=node这个功能,告诉node所有js文件均以esModule的方式引入。

解决方式1:(推荐)

分别添加以下配置,明确当前使用的模块方式和后缀名的解析方法

// package.json
{
"type":"module", // 明确当前项目的js文件均使用esModule的方式进行模块管理
}
// tsconfig.json
{
"ts-node": {
"esm": true,
"experimentalSpecifierResolution": "node", // !!!重要,明确所有不带后缀名的文件均以.js解析
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"target": "ESNext",
"module": "ESNext", // 对应package的type字段
"moduleResolution": "node"
}
},

解决方式2:

明确的在引入包时指定该包的后缀名称,就算在ts文件中也要使用.js,目前并不会影响代码提示

// xxx.ts中
import { coustom_module } from "./coustomModule.js"

解决方式3:

在执行该文件时,添加--experimental-specifier-resolution=node这个特性

# ts-node 如下使用
# 可以对应添加到pacakge.json中
node --experimental-specifier-resolution=node --loader ts-node/esm xxxx.ts
# or
ts-node experimental-specifier-resolution node xxxx.ts