为何TypeScript接口未校验请求体,不符合时无报错?
为什么TypeScript没对不符合接口的请求体报错?
核心原因有三个:
- TypeScript结构类型的特性:TS采用鸭子类型机制,只要对象包含接口要求的所有必填字段,就算多了额外字段,也会被判定为符合接口。TS不会主动校验「是否存在额外字段」,它只关注你有没有满足接口的必填项。
- 编译时检查,运行时无类型:TS的类型检查仅在编译阶段生效,部署后代码会被转成纯JavaScript,接口这类类型定义会被完全移除,运行时根本没有类型信息能用来校验请求体。你代码里的
const newTransaction:NewTransactionPayload = req.body只是编译时的类型标注,运行时不会对req.body做任何过滤或校验。 - 未添加运行时校验逻辑:你现在的代码只是给变量加了类型注解,但没有写任何运行时的校验逻辑。TS本身不提供运行时的请求体校验,要确保请求体严格符合接口,得自己手动过滤字段,或者用Zod、Joi这类专门的校验库来做运行时检查。
解决办法示例:
手动过滤字段
transactionsRouter.post('/', (req, res)=>{ try { // 手动提取接口规定的字段,过滤掉额外内容 const { transactionAmount, transactionDate, transactionWallet, transactionPocket, transactionTag, transactionDetails } = req.body; const newTransaction:NewTransactionPayload = { transactionAmount, transactionDate, transactionWallet, transactionPocket, transactionTag, transactionDetails }; res.status(201).json(newTransaction); } catch (err){ res.status(400).json({error: `Bad request. ${err}`}) } });
用Zod做运行时校验
import { z } from "zod"; // 定义Zod schema(同时支持编译时类型和运行时校验) const NewTransactionSchema = z.object({ transactionAmount: z.number(), transactionDate: z.string(), transactionWallet: z.string(), transactionPocket: z.string(), transactionTag: z.string(), transactionDetails: z.string(), }); // 从schema生成TS类型 type NewTransactionPayload = z.infer<typeof NewTransactionSchema>; transactionsRouter.post('/', (req, res)=>{ try { // 运行时校验请求体,不符合会抛出错误 const newTransaction = NewTransactionSchema.parse(req.body); res.status(201).json(newTransaction); } catch (err){ res.status(400).json({error: `Bad request. ${err}`}) } });
内容的提问来源于stack exchange,提问作者gfek
相关产品推荐
相关产品推荐

