导入insertStudent后TypeScript应用无报错崩溃问题排查
问题分析:导入辅助函数后应用崩溃无提示
在授权控制器中导入insertStudent辅助函数并绑定路由后,应用直接崩溃且无任何错误提示,控制器内的signup函数未执行,但单独调用该辅助函数时运行正常。
相关代码
database.ts 中的 insertStudent 函数
export const insertStudent = async ( firstName: string, middleName: string, lastName: string, email: string, password: string, numberInGrade: number, gradeId: number ): Promise<Student> => { const [rows] = await db.query( "INSERT INTO students (first_name, middle_name, last_name, email, password, number_in_grade, grade_id) VALUES (?, ?, ?, ?, ?, ?, ?); SELECT * FROM students WHERE id = 1461603;", [ firstName, middleName, lastName, email, password, numberInGrade, gradeId, ] ); return rows[1][0] as unknown as Student; };
授权控制器的 signup 函数
import { insertStudent } from "../database.js"; export async function signup(req: Request, res: Response) { const { userType, firstName, middleName, lastName, email, password } = req.body; if ( !userType || !firstName || !middleName || !lastName || !email || !password ) return res.status(400).send({ message: "Please fullfil all fields." }); if (userType === "student") { const { numberInGrade, gradeId } = req.body; if (!numberInGrade || !gradeId) return res .status(400) .send({ message: "Please fullfil all fields." }); const hashedPassword = bcrypt.hashSync(password); try { const user = await insertStudent( firstName, middleName, lastName, email, hashedPassword, numberInGrade, gradeId ); delete user.password; return res .status(201) .send({ message: "Student created successfully", user }); } catch (error) { console.log("error: ", error); return res.status(400).send({ message: "Error creating student" }); } } return res.status(400).send({ message: "Invalid user type" }); }
路由文件 auth.ts
import { Router } from "express"; import { signup } from "../controllers/auth.js"; export const router: Router = Router(); router.post("/signup", signup); export const path = "/auth";
路由通过app.use(path, router);在主文件中注册。
运行报错情况
nodemon 开发模式崩溃
$ npm run dev npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead. > server@1.0.0 dev > nodemon --exec ts-node-esm src/index.ts [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: ts,json [nodemon] starting `ts-node-esm src/index.ts` [nodemon] app crashed - waiting for file changes before starting...
TypeScript 编译为 JS 后报错
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".map" for [PATH REDACTED]\build\routes\auth.js.map at new NodeError (node:internal/errors:377:5) at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:80:11) at defaultGetFormat (node:internal/modules/esm/get_format:122:38) at defaultLoad (node:internal/modules/esm/load:21:20) at ESMLoader.load (node:internal/modules/esm/loader:431:26) at ESMLoader.moduleProvider (node:internal/modules/esm/loader:350:22) at new ModuleJob (node:internal/modules/esm/module_job:66:26) at #createModuleJob (node:internal/modules/esm/loader:369:17) at ESMLoader.getModuleJob (node:internal/modules/esm/loader:328:34) at async Promise.all (index 0) { code: 'ERR_UNKNOWN_FILE_EXTENSION' }
随后仅显示服务器启动信息:Server started on port 8393
package.json 内容
{ "name": "server", "version": "1.0.0", "description": "", "main": "index.js", "type": "module", "scripts": { "start": "node build/index.js", "dev": "nodemon --exec ts-node-esm src/index.ts", "devdb": "nodemon --exec ts-node-esm src/database.ts", "build": "npm run clean && tsc && cp src/.env build/.env", "clean": "rm -rf build", "lint": "eslint . --ext .ts" }, "author": "", "license": "MIT", "dependencies": { "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dayjs": "^1.11.7", "dotenv": "^16.0.3", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", "mysql2": "^2.3.3" }, "devDependencies": { "@types/bcryptjs": "^2.4.2", "@types/cors": "^2.8.13", "@types/express": "^4.17.15", "@types/jsonwebtoken": "^9.0.1", "@types/mysql2": "github:types/mysql2", "@types/node": "^18.11.18", "@typescript-eslint/eslint-plugin": "^5.47.1", "@typescript-eslint/parser": "^5.47.1", "eslint": "^8.30.0", "nodemon": "^2.0.20", "ts-node": "^10.9.1", "typescript": "^4.9.4" } }
问题原因及解决方案
1. 编译后报错:.map 文件导致模块加载失败
编译生成的.map是Source Map调试文件,但Node.js的ESM加载器会错误尝试加载这类文件,导致扩展名识别错误。
解决方法:
- 修改
build脚本,编译后自动删除.map文件:"build": "npm run clean && tsc && cp src/.env build/.env && rm -rf build/**/*.map" - 检查所有导入语句,确保没有误导入
.map后缀的文件。
2. 开发模式无提示崩溃:顶层异步错误未捕获
使用ts-node-esm时,若database.ts中数据库连接初始化等顶层异步操作失败,且未捕获错误,会直接导致进程崩溃且无日志输出。单独调用函数时未触发初始化流程,所以正常运行。
解决方法:
- 在
src/index.ts添加全局错误捕获:process.on('uncaughtException', (err) => { console.error('未捕获异常:', err); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', promise, '原因:', reason); process.exit(1); }); - 给数据库连接添加错误监听:
db.on('error', (err) => { console.error('数据库连接错误:', err); }); - 修改
dev脚本,启用日志追踪:"dev": "nodemon --exec ts-node-esm --trace-warnings src/index.ts"
3. 导入路径与TS配置不匹配
ESM模式下导入路径需严格符合规则,检查tsconfig.json的模块配置:
{ "compilerOptions": { "module": "ESNext", "moduleResolution": "node16", "target": "ESNext", "outDir": "./build", "esModuleInterop": true } }
确保导入时的后缀(如.js)与编译后的文件结构一致。
内容的提问来源于stack exchange,提问作者shestakov-dev
相关产品推荐
相关产品推荐

