Typescript如何检查request.body的对象类型并按类型执行对应逻辑
问题核心原因
TypeScript 所有的类型、接口定义仅存在于编译阶段,编译为JS后会被完全擦除。而
instanceof是JS原生的运行时运算符,要求右侧必须是一个存在的运行时值(通常是构造函数),因此不能直接用仅编译时存在的interface作为instanceof的判断参数。
你封装的校验函数评估
你写的checkObjectType完全无法实现类型校验能力,原因如下:
- 类型断言
as T仅用于向TS编译器声明类型,不会做任何运行时的字段、类型检查 - 该函数的实际逻辑等价于判断传入的
body不是undefined,哪怕传入的对象完全缺少id、name等必填字段,甚至是数字、字符串等非对象类型,只要不是undefined都会返回true,完全达不到校验目的。
正确的实现方案
方案1:手动编写类型守卫(适合简单类型场景)
编写自定义类型守卫函数,运行时检查目标对象的必填字段及对应字段类型:
export interface SomeBodyType { id: string, name: string, // 其他字段 } // 自定义类型守卫 export function isSomeBodyType(obj: unknown): obj is SomeBodyType { // 依次校验:是对象、非空、存在所有必填字段、字段类型符合要求 return typeof obj === 'object' && obj !== null && 'id' in obj && typeof (obj as SomeBodyType).id === 'string' && 'name' in obj && typeof (obj as SomeBodyType).name === 'string'; } // 业务代码中使用 export const someFunction = async (req: Request, res: Response) => { const { body } = req.body; if (isSomeBodyType(body)) { // 该分支内TS会自动将body收窄为SomeBodyType类型,执行函数A } else { // 执行函数B } }
方案2:改为Class实现(适配instanceof语法)
如果要使用instanceof语法,可以将原来的interface改为class,Class是JS原生的运行时存在的构造函数:
export class SomeBodyType { id: string; name: string; constructor(data: unknown) { if ( typeof data !== 'object' || data === null || !('id' in data) || typeof (data as {id: unknown}).id !== 'string' || !('name' in data) || typeof (data as {name: unknown}).name !== 'string' ) { throw new TypeError('不符合SomeBodyType要求'); } this.id = data.id; this.name = data.name; } } // 业务代码中使用 export const someFunction = async (req: Request, res: Response) => { try { const body = new SomeBodyType(req.body.body); // 构造无报错说明类型符合,执行函数A } catch (e) { // 构造失败执行函数B } }
方案3:使用校验库(适合复杂校验、多类型校验场景)
如果项目中存在大量类似的请求体校验需求,可直接使用成熟的校验库,例如Zod、Yup,以Zod为例:
import { z } from 'zod'; // 定义校验规则 const SomeBodySchema = z.object({ id: z.string(), name: z.string(), // 其他字段的校验规则,可自定义格式、必填性、自定义校验逻辑等 }); // 自动导出TS类型,不需要重复编写interface export type SomeBodyType = z.infer<typeof SomeBodySchema>; // 业务代码中使用 export const someFunction = async (req: Request, res: Response) => { const parseResult = SomeBodySchema.safeParse(req.body.body); if (parseResult.success) { // parseResult.data为类型安全的SomeBodyType,执行函数A } else { // 校验失败,parseResult.error可拿到具体的错误信息,执行函数B } }
内容的提问来源于stack exchange,提问作者markWanka
相关产品推荐
相关产品推荐

