如何在TypeScript中让__filename和__dirname成为全局变量?
解决Jest环境下__filename/__dirname全局可访问的方案
方案1:通过Jest Transform自动注入(推荐,适配ESM)
这种方法会给每个JS模块自动添加__filename和__dirname的定义,无需手动导入:
- 项目根目录创建
jest-transform-path.js文件:
export default { process(source, filename) { // 给每个模块注入路径变量的生成代码 return { code: ` import { fileURLToPath } from 'url'; import path from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); ${source} ` }; } };
- 修改
jest.config.js(如果项目是ESM规范,记得用export default导出配置):
export default { // 启用ESM文件支持 extensionsToTreatAsEsm: ['.js'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1' }, // 指定自定义transform处理所有JS文件 transform: { '^.+\\.js$': './jest-transform-path.js' }, testEnvironment: 'node' };
- 更新package.json的测试脚本,添加ESM支持参数:
{ "scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" } }
配置完成后,每个模块里直接使用__filename和__dirname即可,Jest测试时不会出现变量冲突或未定义问题。
方案2:Babel转译适配(适合混合CJS/ESM项目)
如果你的项目可以通过Babel转译为CommonJS,就能直接使用Node.js内置的__filename和__dirname:
- 安装依赖:
npm install --save-dev @babel/core @babel/preset-env @babel/plugin-transform-modules-commonjs babel-jest
- 创建
babel.config.json:
{ "presets": ["@babel/preset-env"], "plugins": ["@babel/plugin-transform-modules-commonjs"] }
- 修改
jest.config.js:
export default { transform: { '^.+\\.js$': 'babel-jest' }, testEnvironment: 'node' };
转译后每个模块会自动获得Node.js内置的__filename和__dirname,无需手动定义。
方案3:全局工具函数(兼容所有环境)
如果不想修改Jest配置,可以写一个全局工具函数,每个模块传入自身的import.meta.url即可获取路径变量:
- 创建
utils/path-utils.js:
import { fileURLToPath } from 'url'; import path from 'path'; export const getPathVars = (metaUrl) => { const __filename = fileURLToPath(metaUrl); const __dirname = path.dirname(__filename); return { __filename, __dirname }; };
- 在任意模块中使用:
import { getPathVars } from './utils/path-utils.js'; const { __filename, __dirname } = getPathVars(import.meta.url);
这种方式不会有Jest兼容性问题,每个模块的路径变量都是基于自身文件生成的。
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

