You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

导入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:56:52