TypeScript如何让函数根据参数返回动态类型(无需显式定义K)
解决TypeScript泛型函数自动推导列类型的问题
问题原因
你原本的写法给泛型K设置了默认值keyof T,当只显式传入T时,TypeScript会直接使用这个默认值,不会从columns参数推导K的实际类型,导致返回的类型总是全量字段的Pick<User, keyof User>[]。
解决方案:使用函数重载
通过重载函数区分传入具体列数组和*的两种场景,既实现自动推导列类型,又保留*的全量查询能力:
// 重载1:传入具体列数组,自动推导选中的字段类型 get<T, K extends keyof T>( tableName: string, columns: K[], where?: (query: Knex.QueryBuilder) => void, trx?: Knex.Transaction ): Promise<Pick<T, K>[]>; // 重载2:传入'*',返回全量字段类型 get<T>( tableName: string, columns: '*', where?: (query: Knex.QueryBuilder) => void, trx?: Knex.Transaction ): Promise<T[]>; // 函数实现 get<T, K extends keyof T>( tableName: string, columns: K[] | '*', where?: (query: Knex.QueryBuilder) => void, trx?: Knex.Transaction ): Promise<Pick<T, K>[] | T[]> { let query = this.withTransaction(tableName, trx).select(columns); if (where) { where(query); } return query; }
使用效果
现在调用时无需显式传入K类型,TypeScript会自动推导:
const user = await this.db.get<User>(USER_TABLE_NAME, ['id', 'username', 'role']); // user 的类型自动推导为 Pick<User, 'id' | 'username' | 'role'>[] // 传入'*'时返回全量字段 const fullUser = await this.db.get<User>(USER_TABLE_NAME, '*'); // fullUser 的类型为 User[]
内容的提问来源于stack exchange,提问作者Kliunkius
相关产品推荐
相关产品推荐

