如何用TypeScript泛型从字符串数组生成指定属性的新类型?
问题场景
现有数据库用户模型的User接口,以及包含对象属性名的数组:
interface User { firstName: string, lastName: string, isActive: boolean, phone: string, // 省略其他大量属性 } const selectedFields = ['firstName', 'lastName'];
需要用TypeScript泛型构建仅包含原接口中选中属性的新类型:
type SelectedUserInterface = { firstName: string, lastName: string, }
已知用as const可以实现,但希望编写泛型工具类型,无需as const和重复typeof ...。尝试了以下代码但失效:
// 尝试1:构建选中属性的类型 type SelectProps<T extends object, K extends (keyof T) & string[]> = Pick<T, K>; // 尝试2:从数组获取字面量联合类型 type ArrayToUnion<T extends readonly any[]> = typeof T[number];
失效原因分析
- 数组类型自动拓宽:
const selectedFields = ['firstName', 'lastName']的默认类型是string[],TypeScript会自动将字面量数组拓宽为通用数组类型,丢失了具体的字面量元素信息,因此无法推导到"firstName" | "lastName"的联合类型。 ArrayToUnion写法错误:类型参数T本身就是数组类型,不需要用typeof,正确写法是T[number]。但即使修正,传入string[]也只能得到string,无法获取字面量联合,根源还是数组类型被拓宽。SelectProps约束矛盾:Pick<T, K>要求K是keyof T的联合类型,而你把K约束为(keyof T) & string[]——数组类型和联合类型无法交叉,约束不成立导致类型推导失败。
解决方案
方案1:用泛型函数推导字面量数组类型(无需as const)
通过泛型函数让TypeScript推导出数组元素的字面量联合类型,避免自动拓宽:
// 泛型函数,用于推导字面量数组类型 function createSelectedFields<T extends string>(fields: T[]) { return fields; } // 此时selectedFields的类型是("firstName" | "lastName")[] const selectedFields = createSelectedFields(['firstName', 'lastName']); // 泛型工具类型:从数组类型提取元素联合类型,再执行Pick type SelectProps<T extends object, K extends readonly (keyof T)[]> = Pick<T, K[number]>; // 生成目标类型 type SelectedUserInterface = SelectProps<User, typeof selectedFields>;
方案2:类型断言配合泛型工具
用类型断言让数组保留字面量类型,再通过泛型工具处理:
// 断言数组类型为User键名组成的数组 const selectedFields = ['firstName', 'lastName'] as (keyof User)[]; // 修正后的泛型工具类型 type SelectProps<T extends object, K extends readonly (keyof T)[]> = Pick<T, K[number]>; // 生成目标类型 type SelectedUserInterface = SelectProps<User, typeof selectedFields>;
方案3:直接用Pick(简洁补充)
如果可以接受直接传入联合类型而非数组,最简洁的方式是直接使用内置的Pick:
type SelectedUserInterface = Pick<User, 'firstName' | 'lastName'>;
内容的提问来源于stack exchange,提问作者crivella
相关产品推荐
相关产品推荐

