You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 18:39:01