TypeScript中如何在类型断言失败时抛出错误?
问题核心说明
TypeScript 的类型仅存在于编译阶段,运行时会被完全擦除,所以你想要的 isInType<School[]>() 这种直接基于泛型参数的运行时校验逻辑无法直接实现——因为运行时根本不知道 School 的结构细节。
要解决 API 响应类型不匹配的问题,必须结合运行时可执行的校验逻辑和 TypeScript 的类型系统,以下是两种可行方案:
方案1:手动编写类型守卫函数
通过自定义类型守卫函数,在运行时检查值的结构,同时让 TypeScript 在编译阶段识别校验后的类型。
// 先定义你的TS类型 type School = { id: number; name: string; address?: string; }; type User = { id: number; username: string; email: string; }; // 单个School的类型守卫:检查必要字段的类型 function isSchool(obj: unknown): obj is School { if (typeof obj !== 'object' || obj === null) return false; const school = obj as School; return typeof school.id === 'number' && typeof school.name === 'string'; } // 扩展为数组类型的守卫:检查数组每一项都符合School类型 function isSchoolArray(arr: unknown): arr is School[] { if (!Array.isArray(arr)) return false; return arr.every(item => isSchool(item)); } // 使用示例 async function fetchSchools() { const response = await fetch("https://test.api.com/Users"); const json = await response.json(); // 注意:原代码漏写了await! if (!isSchoolArray(json)) { throw new Error("响应类型不匹配:预期为School[]"); } // 此处json会被TS自动推断为School[]类型 console.log(json); }
这种方式无需额外依赖,但需要手动为每个目标类型编写校验逻辑,适合结构简单的场景。
方案2:用代码生成工具自动生成校验逻辑
如果不想手动编写重复的校验代码,可以用工具从 TypeScript 类型自动生成运行时校验规则,或者反过来先写校验规则再生成 TS 类型(避免重复劳动)。以 zod 为例:
import { z } from 'zod'; // 先编写运行时的校验schema const SchoolSchema = z.object({ id: z.number(), name: z.string(), address: z.string().optional() }); // 从schema自动生成TS类型 type School = z.infer<typeof SchoolSchema>; // 数组类型的schema const SchoolArraySchema = SchoolSchema.array(); // 使用示例 async function fetchSchools() { const response = await fetch("https://test.api.com/Users"); const json = await response.json(); // 安全校验:失败时返回错误信息,不直接抛出 const validateResult = SchoolArraySchema.safeParse(json); if (!validateResult.success) { throw new Error(`响应类型不匹配:${validateResult.error.message}`); } // validateResult.data 会被TS推断为School[]类型 console.log(validateResult.data); }
这种方式只需要维护一份校验规则,同时得到 TS 类型和运行时校验能力,适合复杂类型或多场景复用的需求。
内容的提问来源于stack exchange,提问作者rogulik
相关产品推荐
相关产品推荐

