使用DTO创建Yup校验遇类型错误及非校验字段处理咨询
问题:结合DTO创建Yup校验规则时遇到类型错误及字段校验疑问
我尝试结合DTO创建Yup校验规则,目前遇到两个错误:
- Yup参数无法分配给ObjectShape类型的参数
- 属性id无法分配给索引签名,number类型无法分配给'Anyschema'类型
移除CargoTypeDetailDto后代码可正常运行。另外咨询:由后端设置的id字段无需校验,除了使用yup.number().notRequired()外是否有其他处理方式?
相关代码
import * as yup from 'yup' import { CargoTypeDetailDto } from '../../../../../api/planning/open-api/models/CargoTypeDetailDto' export const cargoTypeDetailDtoSchema = yup.object(<CargoTypeDetailDto>).shape({ id: yup.number().notRequired(), code: yup .string() .min(1, 'Code can not be below 1') .max(10, 'Code can not be above 10') .required('Code is required'), description: yup .string() .min(1, 'Description can not be below 1') .max(255, 'Description can not be above 255') .required('Description is required'), priceCode: yup.object().shape({ code: yup.string().required('Article code is required'), name: yup.string().required('Article description is required'), }), cargoTypeEuCode: yup.object().shape({ code: yup.string().required('EU code is required'), description: yup.string().required('EU description is required'), }), })
DTO定义
import type { CargoTypeEuCodeDto } from './CargoTypeEuCodeDto'; import type { PriceCodeDto } from './PriceCodeDto'; export type CargoTypeDetailDto = { id: number; code: string; description: string; priceCode: PriceCodeDto; cargoTypeEuCode: CargoTypeEuCodeDto; };
解决方案
一、修复类型错误
你错误地将TypeScript类型CargoTypeDetailDto当作参数传给了yup.object()——TypeScript类型仅存在于编译阶段,运行时无法被代码读取,所以会触发类型不匹配错误。正确做法是用泛型给Yup Schema指定类型:
修改后的代码:
import * as yup from 'yup' // 仅导入类型,避免运行时引用 import type { CargoTypeDetailDto } from '../../../../../api/planning/open-api/models/CargoTypeDetailDto' // 将类型作为泛型参数传入yup.object() export const cargoTypeDetailDtoSchema = yup.object<CargoTypeDetailDto>().shape({ id: yup.number().notRequired(), code: yup .string() .min(1, '编码长度不能小于1') .max(10, '编码长度不能超过10') .required('编码为必填项'), description: yup .string() .min(1, '描述长度不能小于1') .max(255, '描述长度不能超过255') .required('描述为必填项'), priceCode: yup.object().shape({ code: yup.string().required('商品编码为必填项'), name: yup.string().required('商品描述为必填项'), }), cargoTypeEuCode: yup.object().shape({ code: yup.string().required('EU编码为必填项'), description: yup.string().required('EU描述为必填项'), }), })
核心修改点:
- 把
import { CargoTypeDetailDto }改为import type { CargoTypeDetailDto },明确只导入类型 - 将
<CargoTypeDetailDto>作为泛型参数传给yup.object(),而非当作函数参数传入
二、后端生成的id字段的其他处理方式
除了yup.number().notRequired(),还有以下几种方案:
- 完全忽略id字段:如果前端提交数据时不需要携带id,直接从Schema中删除id的定义即可。Yup只会校验Schema中声明的字段,未声明的字段默认会被保留(若要移除未声明字段,可添加
.stripUnknown(true);若要禁止额外字段,可添加.noUnknown(true))。 - 使用
mixed()跳过类型校验:如果不需要限制id的类型,仅需跳过校验,可写yup.mixed().notRequired(),这样任意类型的id都能通过校验。 nullable()+notRequired()组合:如果id可能显式为null或不存在,可写yup.number().nullable().notRequired(),适合后端可能返回null的场景。
内容的提问来源于stack exchange,提问作者JamesG
相关产品推荐
相关产品推荐

