TypeScript处理GraphQL返回数据时提升嵌套对象属性一层的最佳实践
TypeScript 下处理 GraphQL 返回多余嵌套层级的最佳实践
针对Apollo Client自动生成类型的场景,推荐以下3种从优到劣的方案,全部满足类型安全要求:
方案1:使用无副作用的映射函数转换(最推荐)
不要直接修改Apollo返回的原始查询对象(会有缓存异常风险),单独写映射函数生成你需要的扁平化结构,类型完全可控:
// Apollo 自动生成的原始查询类型 interface GeneratedPost { id: string title: string featuredImage?: { node?: { url: string altText: string } } } // 自定义扁平化后的业务使用类型 interface CleanedPost { id: string title: string featuredImage?: { url: string altText: string } } // 类型安全的转换函数 const cleanPostData = (rawData: GeneratedPost): CleanedPost => { return { ...rawData, featuredImage: rawData.featuredImage?.node } } // 拿到查询结果后先转换再使用 const { data } = useQuery(GET_POST) const cleanedData = data ? cleanPostData(data) : undefined
方案2:手动扩展类型修改原对象(仅适合临时场景)
如果你确实需要修改原对象,可以先扩展自动生成的类型,避免赋值报错:
// 扩展原始类型,允许featuredImage为两种结构 type MutablePost = GeneratedPost & { featuredImage?: GeneratedPost['featuredImage'] | CleanedPost['featuredImage'] } const mutableData = data as MutablePost if (mutableData?.featuredImage) { mutableData.featuredImage = mutableData.featuredImage.node }
方案3:通用脱壳工具函数(适合大量重复嵌套场景)
如果你的GraphQL返回有大量{node: T}结构的嵌套,写通用工具函数复用逻辑:
type NodeWrapper<T> = { node?: T } const unwrapNode = <T>(wrapper: NodeWrapper<T> | undefined): T | undefined => { return wrapper?.node } // 多字段复用非常便捷 const cleanPostData = (raw: GeneratedPost): CleanedPost => ({ ...raw, featuredImage: unwrapNode(raw.featuredImage), author: unwrapNode(raw.author), category: unwrapNode(raw.category) })
额外优化建议
如果你使用GraphQL Code Generator生成类型,可以配置自定义插件自动生成转换逻辑,不需要手动编写扁平化类型和映射函数,进一步减少重复工作。
内容的提问来源于stack exchange,提问作者Lars Ejaas
相关产品推荐
相关产品推荐

