如何在TypeScript中创建基于泛型参数类型的属性名的泛型类型?
在TypeScript中创建基于泛型类型名的属性结构
在TypeScript里没法直接通过泛型参数的类型名自动生成属性名——因为类型信息在编译阶段会被擦除,而且TypeScript采用结构类型系统,并非名义类型系统。不过我们可以通过额外传入一个字符串字面量参数来实现你要的通用列表包裹结构,具体方案如下:
核心实现:泛型类型 + 交叉类型
先定义一个泛型类型,同时接收数据类型T和目标属性名字面量K,通过映射类型和交叉类型组合出最终结构:
// 定义通用列表包裹类型 type ListEnvelope<T, K extends string> = { [key in K]: T[]; } & { total: number; skip: number; limit: number; }; // 示例数据类型 interface Product { id: number; title: string; } // 使用类型:显式指定属性名"Products" const productList: ListEnvelope<Product, 'Products'> = { total: 100, skip: 0, limit: 30, Products: [ { id: 1, title: "无线耳机" }, { id: 2, title: "智能手表" } ] };
优化:用辅助函数简化使用
如果不想每次都手动写泛型参数,可以封装一个辅助函数,让TypeScript自动推断数据类型T,只需要传入属性名字面量:
function createListEnvelope<T, K extends string>( data: T[], pagination: { total: number; skip: number; limit: number }, listKey: K ): ListEnvelope<T, K> { return { [listKey]: data, ...pagination } as ListEnvelope<T, K>; } // 使用示例:自动推断T为Product类型 const productList = createListEnvelope( [{ id: 1, title: "无线耳机" }], { total: 100, skip: 0, limit: 30 }, "Products" ); // 另一个示例:用户列表 interface User { id: number; name: string; } const userList = createListEnvelope( [{ id: 1, name: "张三" }], { total: 50, skip: 0, limit: 10 }, "Users" );
为什么不能直接用类型名生成属性名?
TypeScript的类型是结构类型——两个结构相同的类型就算名字不同也会被视为同一类型,编译器不会保留类型的“名称信息”。而且在编译后,所有类型都会被擦除,运行时根本无法获取到泛型参数的类型名,所以必须显式传入属性名字面量。
内容的提问来源于stack exchange,提问作者Rabbi
相关产品推荐
相关产品推荐

