Expo+TypeScript项目通过lint-staged+husky执行tsc自动生成JS文件问题
问题解决:Expo TypeScript项目husky预提交钩子执行tsc异常
问题背景
我有一个基于TypeScript的Expo项目,通过以下命令初始化:
expo init myApp --template @native-base/expo-template-typescript
已配置husky和lint-staged,规则如下:
"lint-staged": { "*.{js,jsx}": [ "eslint --cache --fix" ], "*.{ts,tsx}": [ "tsc --project tsconfig.json", "eslint --cache --fix" ] },
执行预提交钩子时,tsc出现两个异常:
- 错误地检查
node_modules目录下的文件 - 在
src目录生成所有被检查.tsx文件对应的.js文件
但直接执行yarn lint脚本(脚本内容如下)时,完全正常:
"scripts": { ... "lint": "eslint './src/**/*{js,ts,jsx,tsx}' --fix && tsc", ... },
问题原因
- 生成.js文件:默认
tsc会编译TypeScript文件并输出JavaScript产物,但Expo项目无需手动生成编译文件,它会在构建/运行时自行处理。当lint-staged把匹配的具体文件路径传给tsc时,tsc会忽略tsconfig.json中的outDir配置,直接在当前目录生成.js文件。 - 检查node_modules:同样,当
tsc接收具体文件路径时,会忽略tsconfig.json中的exclude配置;如果未启用skipLibCheck,还会强制检查node_modules里的类型定义文件,引发不必要的错误。
解决方案
步骤1:修改tsconfig.json
确保配置以下关键选项:
{ "compilerOptions": { // 保留原有其他配置... "noEmit": true, // 只做类型检查,不生成任何编译文件 "skipLibCheck": true // 跳过node_modules中类型定义文件的检查 }, "exclude": [ "node_modules", "babel.config.js", "metro.config.js", "jest.config.js" // 根据项目实际情况添加需排除的文件/目录 ] }
noEmit:彻底解决生成.js文件的问题,我们只需要tsc做类型校验,无需输出产物。skipLibCheck:跳过node_modules里的类型文件检查,避免无意义的错误。exclude:明确排除无需检查的目录,确保tsc不会处理这些内容。
步骤2:调整lint-staged配置
修改lint-staged中ts/tsx的规则,避免tsc接收lint-staged传递的具体文件路径(会导致tsconfig配置失效):
"lint-staged": { "*.{js,jsx}": [ "eslint --cache --fix" ], "*.{ts,tsx}": [ "bash -c 'tsc --project tsconfig.json'", "eslint --cache --fix" ] },
或者,如果你已经在tsconfig中添加了noEmit,也可以直接写:
"*.{ts,tsx}": [ "tsc --project tsconfig.json --noEmit --skipLibCheck", "eslint --cache --fix" ]
这样即使lint-staged传递文件参数,--noEmit和--skipLibCheck也会强制生效,避免生成文件和检查node_modules。
验证
修改完成后尝试提交代码,此时husky调用tsc应该只会执行类型检查,不会生成.js文件,也不会检查node_modules目录。
内容的提问来源于stack exchange,提问作者Naji
相关产品推荐
相关产品推荐

