无本地配置与依赖 单文件用TS-Node运行全局Google ZX报错
单文件ZX+TS-Node无本地依赖实现方案
核心需求
- 编写可直接运行的单文件TypeScript脚本,无需本地
tsconfig.json、node_modules目录、package.json文件 - 脚本使用体验和常规单文件Shell脚本一致,可直接加执行权限运行
- 依赖全局安装的
zx、ts-node、typescript包,不需要在脚本目录单独安装依赖
问题复现
初始脚本写法如下,运行时抛出Error TS2592: Cannot find name '$'错误,仅当zx安装到本地./node_modules时可正常运行:
#!/usr/bin/env -S ts-node-esm --compilerOptions='{"module": "es2022"}' import 'zx/globals'; await $`echo it works ${JSON.stringify(foo(1))}`; function foo(num: number): number[] { return [num, num * 2, num * 3]; }
报错原因
- Node.js默认不会从全局npm模块目录加载依赖,运行时无法定位全局安装的zx包
- ts-node默认的类型解析路径不包含全局npm模块目录,无法识别zx注入的全局
$等API的类型声明
解决方案
前置准备
先全局安装所需依赖:
npm install -g zx ts-node typescript
方案1:保留全局API写法(推荐)
修改脚本第一行shebang配置,自动注入全局模块路径,同时指定TS类型解析路径,适配不同操作系统的全局npm目录:
#!/usr/bin/env -S NODE_PATH=$(npm root -g) ts-node-esm --compilerOptions='{"module":"es2022","typeRoots":["'$(npm root -g)'"],"types":["zx"]}' import 'zx/globals'; await $`echo it works ${JSON.stringify(foo(1))}`; function foo(num: number): number[] { return [num, num * 2, num * 3]; }
给脚本加执行权限后即可直接运行:
chmod +x ./your-script.ts ./your-script.ts
方案2:显式导入API(配置更简洁)
如果不需要zx的全量全局API,可以改用显式导入的写法,不需要额外配置TS类型解析规则,shebang更短:
#!/usr/bin/env -S NODE_PATH=$(npm root -g) ts-node-esm --compilerOptions='{"module": "es2022"}' import { $ } from 'zx'; await $`echo it works ${JSON.stringify(foo(1))}`; function foo(num: number): number[] { return [num, num * 2, num * 3]; }
兼容性说明
如果shebang中的$(npm root -g)命令替换在你的运行环境不生效,可以先手动执行npm root -g拿到全局node_modules的绝对路径,替换掉命令替换部分硬编码即可,个人固定环境使用无任何问题。
内容的提问来源于stack exchange,提问作者phip1611
相关产品推荐
相关产品推荐

