如何将Drizzle pg的SelectedFields转换为普通类型?
解决Drizzle仓库模式中SelectedFields返回类型不匹配问题
核心问题是Drizzle的SelectedFields类型属于内部列类型集合,无法直接映射到查询返回的普通对象类型,需要借助Drizzle内置的类型工具推导正确的返回类型。
解决方案步骤
- 引入Drizzle内置的类型工具,专门处理查询结果的类型转换
- 修改
BaseRepository中findFirstBy方法的泛型定义,分别处理传参和不传参的类型推导逻辑
完整代码示例
修改后的BaseRepository实现
import { PgTable, SelectedFields, Where, SelectedFieldsFlat, GetSelectResult } from 'drizzle-orm/pg-core'; import { db } from './your-db-connection'; // 替换为你的数据库连接实例 class BaseRepository<T extends PgTable> { constructor(public table: T) {} async findFirstBy<Select extends SelectedFields<T> | undefined = undefined>( where: Where<T>, select?: Select ): Promise< Select extends undefined ? T['$inferSelect'] // 使用表内置的查询结果推断类型 : GetSelectResult<T, SelectedFieldsFlat<Select>> > { const query = db.select(select || this.table).from(this.table).where(where).limit(1); return await query; } }
调用示例
// 示例表定义 import { pgTable, serial, varchar, eq } from 'drizzle-orm/pg-core'; const users = pgTable('users', { id: serial('id').primaryKey(), name: varchar('name', { length: 255 }), email: varchar('email', { length: 255 }).unique(), }); // 初始化仓库实例 const userRepo = new BaseRepository(users); // 场景1:不传select参数,返回完整表结构类型 const fullUser = await userRepo.findFirstBy(eq(users.id, 1)); // fullUser类型:{ id: number; name: string; email: string } // 场景2:传select参数,返回选中字段的扁平普通类型 const partialUser = await userRepo.findFirstBy( eq(users.id, 1), { name: users.name, email: users.email } ); // partialUser类型:{ name: string; email: string }
关键类型说明
SelectedFieldsFlat<Select>:将传入的SelectedFields转换为扁平的列集合类型,自动处理嵌套或别名列的结构GetSelectResult<T, SelectedFieldsFlat<Select>>:基于表结构和扁平列集合,推导出与实际查询结果完全匹配的普通对象类型T['$inferSelect']:Drizzle表类型内置的推断属性,用于获取完整表查询的返回类型,比直接使用T更准确
内容的提问来源于stack exchange,提问作者CodeRevenge
相关产品推荐
相关产品推荐

