如何让TypeScript的select泛型函数返回指定参数对应的T子集类型?
解决方案
你需要给select函数新增一个泛型参数K,用来捕获传入列名的联合类型,同时约束它只能是T的键的子集,最终返回Pick<T, K>类型。具体实现如下:
// 补充Model基础接口定义(假设你已有此接口,这里仅为完整示例) interface Model {} interface User extends Model { id: number; name: string; age: number; } function select<T extends Model, K extends keyof T>(...columns: K[]): Pick<T, K> { // 此处编写实际业务逻辑(比如从数据源筛选字段) // 类型断言仅为临时占位,实际实现需保证返回结构与类型匹配 return {} as Pick<T, K>; }
效果验证
保留参数合法性校验:传入非
T的键会触发报错select<User>("id", "email"); // 报错:"email"不属于User的键,符合预期返回类型自动匹配传入字段:
const example = select<User>("id", "name"); // typeof example 为 { id: number; name: string },不包含age字段,完全符合需求无需冗余类型声明:不用手动编写
Pick<User, "id" | "name">,TypeScript会自动推导K为"id" | "name"
方案原理
- 泛型
K通过K extends keyof T严格约束,确保传入的列名都是T的合法键,保留了原有的参数校验能力。 - 返回类型
Pick<T, K>是TypeScript内置工具类型,专门用于从T中提取指定键K对应的子类型,精准实现“仅返回传入字段的对象”的需求。 - 调用时只需显式指定
T(如User),K会根据传入的列名自动推导,避免了重复写列名的冗余操作。
对比之前的问题
- 你之前尝试的单泛型方案,因未捕获具体列名类型,返回类型只能覆盖
T的所有键,无法精准匹配传入字段;且不指定T时,TypeScript会推导包含任意传入键的类型,导致非法字段被允许。 - 手动指定
Pick<User, ...>的方式需要重复编写列名,既冗余又易出错,本方案通过自动推导K彻底解决了这个问题。
内容的提问来源于stack exchange,提问作者David Rodrigues
相关产品推荐
相关产品推荐

