如何基于Yup Schema过滤数组中的无效元素?
解决方案:过滤数组中的无效元素
要实现只保留数组中符合校验规则的元素,你需要逐个校验数组元素,捕获校验失败的实例,仅保留校验成功的结果。直接使用数组级别的Schema校验会因单个元素失败而整体报错,因此需要拆分处理:
1. 编写过滤函数
创建异步函数遍历输入数组,对每个元素单独执行校验,收集通过校验的结果:
import { someSchema, SomeType } from './your-schema-file'; async function filterValidItems(data: unknown): Promise<SomeType[]> { // 非数组输入直接返回空数组 if (!Array.isArray(data)) return []; // 用Promise.allSettled处理所有异步校验,不中断流程 const results = await Promise.allSettled( data.map(item => someSchema.validate(item, { abortEarly: false })) ); // 过滤并收集校验成功的元素 return results.reduce<SomeType[]>((validItems, result) => { if (result.status === 'fulfilled') { validItems.push(result.value); } return validItems; }, []); }
2. 关键细节说明
Promise.allSettled的作用:它会等待所有异步校验完成,无论成功或失败,不会因单个元素校验失败而终止整个流程,这是与Promise.all的核心区别。- 保留Schema转换逻辑:
someSchema中的.from('date', 'startDate')字段转换会在单个元素校验时自动执行,最终返回的有效元素会包含转换后的startDate字段。 - 类型安全保障:校验通过的元素必然符合
SomeType类型,因此类型断言是安全的,最终返回数组的类型为SomeType[],与原someListSchema对应的类型一致。
3. 替代方案:自定义数组Schema的transform(可选)
如果你希望通过数组Schema直接实现过滤,可以给someListSchema添加transform方法,在转换阶段自动过滤无效元素:
import { array } from 'yup'; import { someSchema } from './your-schema-file'; export const someListSchema = array() .of(someSchema) .transform(async (value) => { if (!Array.isArray(value)) return []; // 复用上面的过滤函数 const validItems = await filterValidItems(value); return validItems; });
之后你可以直接调用await someListSchema.validate(data),它会自动返回过滤后的有效元素数组。
为什么之前的尝试未成功?
{ abortEarly: false }仅会让数组校验返回所有错误,但不会过滤无效元素,仍会整体抛出错误。- 若你之前尝试逐个遍历但失败,大概率是未正确处理异步校验的错误捕获,或是忽略了Schema中的字段转换(如
.from)需要在校验时执行,而非单纯做类型判断。
内容的提问来源于stack exchange,提问作者Bear
相关产品推荐
相关产品推荐

