如何用TypeScript实现支持多参数组合的文档/对象获取函数?
问题2:实现类型安全的getObjects函数
类型定义(修正语法错误后)
type PersonDoc = { personId: string; age: number } type ProjectDoc = { projectId: string; title: string } type OrganizationDoc = { organizationId: string; name: string }
需求
实现getObjects函数:
- 接收
personId、projectId、organizationId的任意组合作为参数 - 返回包含对应类型对象的结果,示例:
getObjects({ personId: "abc" })→{person: {personId: "abc", age: 35}}getObjects({ personId: "abc", projectId: "def" })→ 包含PersonDoc和ProjectDoc的对象getObjects({ projectId: "def", organizationId: "qrs" })→ 包含ProjectDoc和OrganizationDoc的对象
解决方案
通过TypeScript映射类型实现参数与返回值的类型联动:
// 定义ID字段到文档类型和结果键的映射 type IdToDocMap = { organizationId: { key: 'organization'; type: OrganizationDoc }; personId: { key: 'person'; type: PersonDoc }; projectId: { key: 'project'; type: ProjectDoc }; }; // 参数类型:任意ID字段的可选组合 type GetObjectsParams = Partial<{ [K in keyof IdToDocMap]: string }>; // 返回类型:根据传入的ID字段自动生成对应文档的键值对 type GetObjectsResult<T extends GetObjectsParams> = { [K in keyof T as T[K] extends string ? IdToDocMap[K]['key'] : never]: IdToDocMap[Extract<K, keyof IdToDocMap>]['type']; }; function getObjects<T extends GetObjectsParams>(params: T): GetObjectsResult<T> { const result: any = {}; // 生成组织文档(模拟数据,实际可替换为数据库查询) if (params.organizationId) { result.organization = { organizationId: params.organizationId, name: `组织-${params.organizationId}` } as OrganizationDoc; } // 生成人员文档 if (params.personId) { result.person = { personId: params.personId, age: 35 } as PersonDoc; } // 生成项目文档 if (params.projectId) { result.project = { projectId: params.projectId, title: `项目-${params.projectId}` } as ProjectDoc; } return result as GetObjectsResult<T>; }
使用示例
// 仅传入personId const res1 = getObjects({ personId: "abc" }); // res1类型:{ person: PersonDoc },值为 { person: { personId: "abc", age: 35 } } // 传入personId和projectId const res2 = getObjects({ personId: "abc", projectId: "def" }); // res2类型:{ person: PersonDoc; project: ProjectDoc } // 传入projectId和organizationId const res3 = getObjects({ projectId: "def", organizationId: "qrs" }); // res3类型:{ project: ProjectDoc; organization: OrganizationDoc }
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

