NestJS中Drizzle ORM插入数据时TS2769类型匹配错误
错误信息
TS2769: No overload matches this call.
Overload 1 of 2, '(values: (Insertable| Insertable []) & { onConflict?: OnConflictBuilder | undefined; }): Promise<...>', gave the following error.
Type '{ customerSegment: string; ... }' is not assignable to type 'Insertable'.
Object literal may only specify known properties, and 'customerSegment' does not exist in type 'Insertable'.
相关代码片段
Drizzle生成的Schema(users表)
// drizzle/schema/users.ts import { mysqlTable, varchar, int } from 'drizzle-orm/mysql-core'; export const users = mysqlTable('users', { id: int('id').primaryKey().autoincrement(), name: varchar('name', { length: 255 }).notNull(), customer_segment: varchar('customer_segment', { length: 50 }).notNull(), }); export type InsertUser = typeof users.$inferInsert;
NestJS Service层代码
// src/users/users.service.ts import { Injectable } from '@nestjs/common'; import { db } from '../../drizzle/db'; import { users, InsertUser } from '../../drizzle/schema/users'; @Injectable() export class UsersService { async createUser(userData: { name: string; customerSegment: string }) { // 此处触发TS2769错误 const result = await db.insert(users).values(userData); return result; } }
解决方法
1. 处理字段命名映射(驼峰 vs 蛇形)
这是最常见的原因:Drizzle默认保留数据库的蛇形命名(如customer_segment),但代码中使用驼峰命名(customerSegment),TypeScript会严格校验类型。
方法一:手动转换字段名
将传入的驼峰字段手动映射为数据库的蛇形字段:
async createUser(userData: { name: string; customerSegment: string }) { const mappedData = { name: userData.name, customer_segment: userData.customerSegment, }; const result = await db.insert(users).values(mappedData); return result; }
方法二:启用Drizzle驼峰自动转换
在Drizzle数据库配置中开启驼峰转换,自动处理命名映射:
// drizzle/db.ts import { drizzle } from 'drizzle-orm/mysql2'; import mysql from 'mysql2/promise'; import { users } from './schema/users'; const pool = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, }); // 启用casing: 'camelCase',自动将数据库蛇形字段映射为代码驼峰字段 export const db = drizzle(pool, { schema: { users }, casing: 'camelCase', });
开启后,InsertUser类型会自动生成为驼峰字段,Service层直接使用customerSegment即可,无需手动转换。
2. 修正类型推断与导入
确保使用正确的Drizzle推断类型:
- 确认导入的
InsertUser是从正确的schema文件导出的 - 直接用
InsertUser作为入参类型,提前校验传入数据:
async createUser(userData: InsertUser) { const result = await db.insert(users).values(userData); return result; }
3. 过滤额外字段
如果传入的userData包含schema中未定义的字段,需过滤后再插入:
async createUser(userData: { name: string; customerSegment: string; extraField: string }) { // 只保留schema中存在的字段 const filteredData = { name: userData.name, customer_segment: userData.customerSegment, }; const result = await db.insert(users).values(filteredData); return result; }
注:非必要不使用类型断言(如as unknown as InsertUser),会隐藏真实类型问题。
内容的提问来源于stack exchange,提问作者James Caranay

