You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 20:39:03