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

如何在Express中间件中为req.body分配基于Yup Schema的类型?

为Express Yup验证中间件动态设置req.body类型

你可以通过给验证中间件添加泛型参数,结合Yup的InferType工具类型,实现让req.body自动匹配传入Schema的类型。下面是具体的改造方案:

原问题代码

验证中间件

import { NextFunction, Request, Response } from 'express'
import { Schema, ValidationError } from 'yup'

export default function validate(schema: Schema) {
  return async (req: Request, res: Response, next: NextFunction) => {
    try {
      const body = await schema.validate(req.body, {
        stripUnknown: true
      })

      // TODO: Is there a way to dynamically type this to the type of the schema?
      req.body = body

      next()
    } catch (error) {
      if (error instanceof ValidationError) {
        return res.status(400).json({ message: error.message })
      }
      return res.status(500).json({ message: 'Unknown error' })
    }
  }
}

路由使用示例

import { object, string } from 'yup'

// ...

const schema = object({
  name: string().required()
})

app.put('/test/:id', validate(schema), async (req, res) => {
  // ...

  req.body.name // 当前类型为any,期望是Schema定义的string类型
  req.body.unknownProperty // 期望此处因不属于Schema而报错
  
  // ...
})

改造方案

1. 给验证中间件添加泛型支持

修改中间件代码,引入泛型关联Schema类型,通过yup.InferType推导对应TS类型,并扩展Express的Request类型覆盖body字段:

import { NextFunction, Request, Response } from 'express'
import { Schema, ValidationError, InferType } from 'yup'

// 定义泛型验证函数,T绑定传入的Schema类型
export default function validate<T extends Schema>(schema: T) {
  // 用泛型Request覆盖body的类型定义
  return async (req: Request<{}, {}, InferType<T>>, res: Response, next: NextFunction) => {
    try {
      // validate返回的body自动匹配InferType<T>类型
      const body = await schema.validate(req.body, {
        stripUnknown: true
      })

      req.body = body

      next()
    } catch (error) {
      if (error instanceof ValidationError) {
        return res.status(400).json({ message: error.message })
      }
      return res.status(500).json({ message: 'Unknown error' })
    }
  }
}

2. 路由中自动获得类型提示

现在在路由里使用validate(schema)时,TypeScript会自动根据传入的Schema推导req.body的类型:

import { object, string } from 'yup'

// ...

const schema = object({
  name: string().required()
})

app.put('/test/:id', validate(schema), async (req, res) => {
  // req.body.name 类型为 string(符合预期)
  console.log(req.body.name)

  // req.body.unknownProperty 会触发TypeScript错误(符合预期)
  console.log(req.body.unknownProperty)
  
  // ...
})

原理说明

  • InferType<T>:Yup提供的工具类型,能从Yup Schema反向推导出对应的TypeScript类型。
  • 泛型T extends Schema:确保传入参数是合法的Yup Schema,同时让TypeScript捕获具体的Schema类型。
  • Request<{}, {}, InferType<T>>:Express的Request类型有三个泛型参数,分别对应params、query、body,这里仅修改第三个参数指定body的类型。

内容的提问来源于stack exchange,提问作者Dennis Martinez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:35:20