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

如何在TypeScript中为mysql2的查询结果添加强类型?

解决方案:为MySQL查询结果添加强类型,解决insertId类型报错

问题根源

你的executeQuery函数返回了MySQL2的多种结果类型(RowDataPacket[]/ResultSetHeader等)加上错误对象的联合类型,TypeScript无法确定执行INSERT语句后返回的是包含insertId的ResultSetHeader,因此抛出类型错误。同时原函数的错误处理方式(返回{ error })进一步模糊了返回值类型。


步骤1:重构executeQuery函数,添加泛型与正确错误处理

修改lib/db.ts,让函数支持泛型指定返回类型,并通过抛出错误替代返回错误对象,确保返回值类型纯净:

import mysql from "mysql2/promise";
import type { RowDataPacket, ResultSetHeader, OkPacket } from "mysql2/promise";

// 定义MySQL查询可能的结果类型
type QueryResult = RowDataPacket[] | ResultSetHeader | OkPacket;

export const executeQuery = async <T extends QueryResult>(
  query: string,
  params: unknown[] = []
): Promise<T> => {
  const db = await mysql.createConnection({
    host: process.env.MYSQL_HOST,
    database: process.env.MYSQL_DATABASE,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
  });

  try {
    // 用泛型T指定execute的返回类型
    const [results] = await db.execute<T>(query, params);
    return results;
  } catch (error) {
    // 抛出错误,让调用方通过try/catch处理
    throw new Error(`数据库查询失败: ${(error as Error).message}`);
  } finally {
    // 确保无论成功失败都关闭连接
    await db.end();
  }
};

步骤2:在API端点中指定返回类型并处理错误

修改你的API文件,明确指定INSERT语句的返回类型为ResultSetHeader,并通过try/catch捕获错误:

import { hash } from "bcrypt";
import type { NextApiRequest, NextApiResponse } from "next";
import randomstring from "randomstring";
import type { ResultSetHeader } from "mysql2/promise";

import { executeQuery } from "../../../lib/db";

const Test = async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    // 生成并加密密码(修复原代码中缺少await的问题)
    const password = randomstring.generate(16);
    const hashedPassword = await hash(password, 10);

    // 指定返回类型为ResultSetHeader,TypeScript会识别insertId属性
    const auth = await executeQuery<ResultSetHeader>(
      "INSERT INTO auth (email, password) VALUES (?, ?)",
      ["test@test.com", hashedPassword.toString()]
    );

    res.status(200).json({ insertId: auth.insertId });
  } catch (error) {
    res.status(500).json({ error: (error as Error).message });
  }
};

export default Test;

扩展:处理其他查询类型

对于SELECT等查询,只需指定对应的返回类型即可:

// 查询用户列表,指定返回RowDataPacket[]
const users = await executeQuery<RowDataPacket[]>("SELECT * FROM users WHERE role = ?", ["admin"]);
// 此时可正常访问users[0].email等字段

内容的提问来源于stack exchange,提问作者Nextrati

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 02:35:23