如何在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
相关产品推荐
相关产品推荐

