使用Knex的MAX方法时出现“is not assignable to type”类型不匹配错误
看起来你碰到了Knex查询返回值和自定义类型不兼容的问题,我来帮你理清楚问题出在哪,以及怎么解决:
问题根源
你定义的StudentGroup类型里,student_max_score被设为了纯number类型,但因为你用了leftJoin关联student表——如果某个学生组没有对应的学生记录,MAX(student.score)的结果会是null。Knex会准确推断这个字段的类型是number | null,这就和你定义的纯number类型冲突了,所以抛出了“is not assignable to type”的错误。
另外顺便提一句,你代码里name: number应该是笔误吧?学生组的名称怎么会是数字类型呢?改成name: string才合理,这个小错误也可能给你带来额外的类型问题哦。
解决办法
这里给你两个常用的解决思路,你可以根据业务场景选:
调整类型定义(最直接)
既然查询结果可能返回null,那直接把StudentGroup里的student_max_score类型改成number | null,让它和Knex的返回类型对齐:type StudentGroup = { student_group_id: number, id: number, name: string, student_max_score: number | null, }用
coalesce把null转成默认值
如果你的业务逻辑能保证每个学生组都有对应的学生,或者允许把无学生的组的最高分设为0(或其他默认值),可以用SQL的coalesce函数把null替换成具体数字,这样返回的就是纯number类型了,同时别忘了聚合查询必须加group by(不然数据库会报错):public async getTopGroupByScores(): Promise<StudentGroup[]> { return knex("student_group") .leftJoin("student", { "student.id": "student_group.student_id" }) .max(knex.raw("coalesce(student.score, 0) as student_max_score")) .select([ "student_group.student_group_id", "student_group.id", "student_group.name" ]) .groupBy("student_group.student_group_id", "student_group.id", "student_group.name"); }
对了,你的原查询里还漏了group by子句,用MAX这类聚合函数时,必须把所有非聚合的查询字段都放在group by里,否则数据库会抛出语法错误,这也是你需要补上的点。
内容来源于stack exchange

