React中API响应类型多变时,如何反序列化为TypeScript类型?
针对不同用户类型的搜索结果反序列化方案
针对你的React+TypeScript场景,以下是几种实用的类型反序列化方案:
方案1:自定义类型守卫(Type Guards)
这是处理联合类型最直接的前端方案,无需修改API,通过检查响应中独有的字段来判别具体类型。
假设你的接口补充示例字段后为:
export interface AnonymousSearchResults { basicResults: string[]; } export interface MemberSearchResults extends AnonymousSearchResults { memberExclusiveContent: string[]; } export interface AdminSearchResults extends MemberSearchResults { adminControls: string[]; } export type SearchResults = AnonymousSearchResults | MemberSearchResults | AdminSearchResults;
编写自定义类型守卫函数:
// 判断是否为会员搜索结果 function isMemberResults(res: SearchResults): res is MemberSearchResults { return 'memberExclusiveContent' in res; } // 判断是否为管理员搜索结果 function isAdminResults(res: SearchResults): res is AdminSearchResults { return 'adminControls' in res; }
实际使用时:
async function fetchSearchResults() { const response = await fetch('/api/search'); const rawData = await response.json(); const results = rawData as SearchResults; // 先做基础类型断言 if (isAdminResults(results)) { // TS自动推断results为AdminSearchResults类型 console.log(results.adminControls); } else if (isMemberResults(results)) { // TS自动推断results为MemberSearchResults类型 console.log(results.memberExclusiveContent); } else { // TS自动推断results为AnonymousSearchResults类型 console.log(results.basicResults); } }
方案2:标签联合类型(Tagged Union)
如果能协调后端在响应中添加一个标识用户类型的字段(如userType),可以用标签联合类型让TS自动做类型判别,代码更简洁。
调整接口定义:
export interface AnonymousSearchResults { userType: 'anonymous'; basicResults: string[]; } export interface MemberSearchResults extends AnonymousSearchResults { userType: 'member'; memberExclusiveContent: string[]; } export interface AdminSearchResults extends MemberSearchResults { userType: 'admin'; adminControls: string[]; } export type SearchResults = AnonymousSearchResults | MemberSearchResults | AdminSearchResults;
使用时无需额外守卫函数:
async function fetchSearchResults() { const response = await fetch('/api/search'); const results = await response.json() as SearchResults; switch(results.userType) { case 'admin': console.log(results.adminControls); break; case 'member': console.log(results.memberExclusiveContent); break; case 'anonymous': console.log(results.basicResults); break; } }
方案3:运行时类型校验库(如Zod)
如果需要严格校验API返回数据的合法性(避免后端返回非法数据导致前端报错),可以用专门的校验库,同时生成TS类型。
以Zod为例,先安装依赖:
npm install zod
定义Schema并生成TS类型:
import { z } from 'zod'; const AnonymousSearchResultsSchema = z.object({ basicResults: z.array(z.string()), }); const MemberSearchResultsSchema = AnonymousSearchResultsSchema.extend({ memberExclusiveContent: z.array(z.string()), }); const AdminSearchResultsSchema = MemberSearchResultsSchema.extend({ adminControls: z.array(z.string()), }); const SearchResultsSchema = z.union([ AnonymousSearchResultsSchema, MemberSearchResultsSchema, AdminSearchResultsSchema, ]); // 从Zod Schema自动生成TS类型 export type SearchResults = z.infer<typeof SearchResultsSchema>;
使用时做数据校验:
async function fetchSearchResults() { const response = await fetch('/api/search'); const rawData = await response.json(); // 校验数据,不符合Schema会抛出错误 const results = SearchResultsSchema.parse(rawData); // 后续可通过字段判断具体类型 if ('adminControls' in results) { console.log(results.adminControls); } }
内容的提问来源于stack exchange,提问作者Blankman
相关产品推荐
相关产品推荐

