如何在TypeScript中为类型添加单个动态键以实现接口返回值类型安全?
TypeScript 实现动态实体分页接口的类型安全封装
核心实现逻辑
我们通过TS的泛型、映射类型将实体名称和对应返回结构做绑定,实现入参和返回值的类型关联,全程无需硬编码每个接口的返回类型。
步骤1:定义实体类型与映射表
先声明各业务实体的结构,再维护一个实体名到实体类型的映射表,后续新增实体只需更新该映射表即可:
// 定义各业务实体的具体结构 interface User { id: number username: string email: string } interface Employee { id: number jobNo: string department: string } interface Customer { id: number customerName: string contactPhone: string } // 实体名 -> 实体类型的映射表,key对应接口路径和返回的实体字段名 interface EntityTypeMap { users: User employees: Employee customers: Customer }
步骤2:构造通用分页返回类型
基于通用的分页字段,结合动态实体字段,生成对应接口的返回类型:
// 泛型K为传入的实体名,继承映射表的key type PaginatedResult<K extends keyof EntityTypeMap> = { pages: number pageSize: number } & Record<K, EntityTypeMap[K][]> // 上面的Record<K, EntityTypeMap[K][]>就是动态生成对应实体名的数组字段
步骤3:封装类型安全的fetch函数
将入参的实体名和返回值类型做绑定:
async function fetchPaginatedData<K extends keyof EntityTypeMap>(entityName: K): Promise<PaginatedResult<K>> { const resp = await fetch(`/${entityName}`) // 此处做类型断言,确保返回值符合我们定义的结构 return resp.json() as Promise<PaginatedResult<K>> }
使用效果
调用时只需传入实体名,TS会自动推导返回值的完整结构:
// 传入'users'时,返回值自动识别为 { pages: number; pageSize: number; users: User[] } const userData = await fetchPaginatedData('users') console.log(userData.users) // 自动识别为User数组,访问属性会有代码提示 console.log(userData.pages) // 识别为number类型 // 传入'employees'同理 const empData = await fetchPaginatedData('employees') console.log(empData.employees) // 自动识别为Employee数组
扩展说明
如果需要支持带分页参数的请求,只需在函数入参里添加pages、pageSize等参数即可,类型推导逻辑无需修改。后续新增其他实体接口,只需要在EntityTypeMap里新增对应的键值对,不需要调整封装的基础函数。
内容的提问来源于stack exchange,提问作者user6342701
相关产品推荐
相关产品推荐

