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

TypeScript中mysql2查询结果无法赋值给IUser[]的问题解决

问题描述

我编写了如下Users类:

class Users {
  static async findAll(req: Request, res: Response, next: NextFunction) : Promise<IUser[]> {
    const rows = await Pools.execute("SELECT * FROM users" )
      .then((rows) => {
      return rows[0];
      })
      .catch(err => console.log(err));
    next();
    return rows;
  }
}

但在return rows;处出现错误:

Type 'void | RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[] | ResultSetHeader' is not assignable to type 'IUser[]'.
Type 'void' is not assignable to type 'IUser[]'.

IUser接口定义如下:

import { RowDataPacket } from "mysql2"

interface IUser extends RowDataPacket {
  id?: number;
  email: string;
  password: string;
  username: string;
  admin: boolean;
  created_at: Date;
}

export {IUser};

已知rows[0]的实际数据结构如下:

[
  {
    "id": 1,
    "email": "admin@u.com",
    "password": "12345",
    "username": "admin@u.com",
    "admin": 1,
    "created_at": "2023-01-06T02:31:14.000Z"
  },
  {
    "id": 2,
    "email": "u@u.com",
    "password": "12345",
    "username": "u@u.com",
    "admin": 0,
    "created_at": "2023-01-06T03:08:20.000Z"
  }
]

请问该错误产生的原因是什么,如何修复?


错误原因

  • catch块无返回值导致类型混入void:你在Pools.execute()的catch回调里只打印错误,没有返回任何值,这会让Promise的返回类型包含void,但函数声明必须返回Promise<IUser[]>,类型不兼容。
  • TypeScript无法自动推断返回类型:mysql2的execute()返回的是多种类型的联合(比如RowDataPacket、OkPacket),TS无法自动识别rows[0]就是你定义的IUser[],需要手动断言类型。
  • 字段类型不匹配:数据库中admin字段存储的是数字1/0,但IUser接口里定义的是boolean类型,这也会触发类型校验失败。

修复方案

1. 重构错误处理,避免void类型

把Promise链的catch换成try/catch结构,这样错误时要么抛出错误让后续中间件处理,要么返回符合类型的默认值,不会让rows变量混入void类型。

2. 显式类型断言+字段类型转换

将查询结果断言为RowDataPacket[],再把admin字段从数字转换为布尔值,最后断言为IUser[]。

修复后的完整代码

class Users {
  static async findAll(req: Request, res: Response, next: NextFunction): Promise<IUser[]> {
    try {
      // 解构获取查询结果,替代rows[0]的写法更直观
      const [rows] = await Pools.execute("SELECT * FROM users");
      // 转换admin字段类型,并断言为IUser数组
      const users = (rows as RowDataPacket[]).map(row => ({
        ...row,
        admin: row.admin === 1,
        created_at: new Date(row.created_at)
      })) as IUser[];
      next();
      return users;
    } catch (err) {
      console.log(err);
      // 抛出错误让中间件处理,或者返回空数组[]
      throw err;
    }
  }
}

可选优化:用mysql2泛型简化类型断言

mysql2的execute方法支持泛型参数,可以直接指定返回的行类型,减少手动断言的代码:

class Users {
  static async findAll(req: Request, res: Response, next: NextFunction): Promise<IUser[]> {
    try {
      // 通过泛型指定返回的行类型为RowDataPacket[]
      const [rows] = await Pools.execute<RowDataPacket[]>("SELECT * FROM users");
      const users = rows.map(row => ({
        ...row,
        admin: row.admin === 1,
        created_at: new Date(row.created_at)
      })) as IUser[];
      next();
      return users;
    } catch (err) {
      console.log(err);
      throw err;
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:01:44