TypeScript泛型仓库类如何强制指定所有查询字段并避免重复定义?
解决方案
1. 自动推断返回类型,避免重复定义
通过让方法从传入的findFields数组字面量自动推断返回类型,无需手动定义tablePartial这类Pick类型。同时利用as const让TypeScript保留数组元素的字面量类型,确保类型推断准确。
改造后的BaseRepository类:
export default abstract class BaseRepository<T> { // 原有全字段查询方法 public async findEntities(conditionFieldsObj: Partial<T>): Promise<T[]> { // 数据库查询逻辑:select * from table where ... return []; } // 改造后的部分字段查询方法 async findEntitiesPartial<Keys extends readonly (keyof T)[]>( conditionFieldsObj: Partial<T>, findFields: Keys ): Promise<Pick<T, Keys[number]>[]> { // 数据库查询逻辑:select ${findFields.join(',')} from table where ... return []; } }
调用方式:
// 无需手动定义tablePartial,直接从findFields推断返回类型 const result = await table1.findEntitiesPartial( { column1filter: "something" }, ["column1", "column2"] as const // 必须加as const,让TypeScript识别字面量键集合 ); // result的类型自动为 Pick<tableEntity, "column1" | "column2">[]
2. 强制findFields包含所有目标列
如果确实需要手动指定返回类型(比如提前定义好常用的部分字段类型),可以通过类型约束强制findFields必须包含该类型的所有键:
export default abstract class BaseRepository<T> { async findEntitiesPartial<D extends Partial<T>>( conditionFieldsObj: Partial<T>, // 约束findFields必须包含D的所有键 findFields: Array<keyof D> & (keyof D extends typeof findFields[number] ? unknown : never) ): Promise<D[]> { // 数据库查询逻辑 return []; } }
调用示例(此时如果findFields漏掉D中的键,TypeScript会报错):
type tablePartial = Pick<tableEntity, "column1" | "column2">; // 正确调用:包含所有tablePartial的键 const result = await table1.findEntitiesPartial<tablePartial>( { column1filter: "something" }, ["column1", "column2"] ); // 错误调用:漏掉column2,TypeScript会提示类型不匹配 const badResult = await table1.findEntitiesPartial<tablePartial>( { column1filter: "something" }, ["column1"] );
最优实践
优先使用第一种自动推断的方案,既避免了重复定义列名,又能通过as const确保findFields和返回类型完全匹配,从根源上杜绝列名遗漏的问题。
内容的提问来源于stack exchange,提问作者user678272
相关产品推荐
相关产品推荐

