如何用io-ts验证数组长度?求通用的长度范围校验方案
实现io-ts通用数组长度范围校验器
我来帮你搞定这个io-ts的数组长度校验问题,你的思路方向是对的,但原代码里有几个关键细节没处理好,导致无法运行。下面我一步步给你修正,实现一个支持任意元素类型的通用版本:
先说说原代码的核心问题
t.array的使用方式错了:t.array是一个工厂函数,必须传入元素对应的codec(比如t.string、t.number)才能生成具体的数组codec,不能直接用t.array本身。- 类型注解缺失泛型:你写的
(n: Array)没有指定泛型参数,TypeScript会报错,数组类型需要明确元素类型。 - 品牌类型不够灵活:原有的
IMinMaxArray没有和元素类型绑定,会导致不同元素类型的数组校验器可能出现类型混淆。
通用实现方案
首先我们定义一个带泛型的品牌类型,确保不同元素类型的校验器类型唯一,同时可以带上min/max元数据方便后续调试:
import * as t from 'io-ts'; // 定义带泛型的品牌类型,绑定元素类型和校验规则参数 interface MinMaxArrayBrand<T> { readonly MinMaxArray: unique symbol; readonly min: number; readonly max: number; readonly elementType: T; }
然后实现通用的minMaxArray校验器函数,它接受三个参数:元素codec、最小长度、最大长度:
const minMaxArray = <T extends t.Mixed>(elementCodec: T, min: number, max: number) => t.brand( // 先基于传入的元素codec创建对应的数组codec t.array(elementCodec), // 类型守卫:校验数组长度是否在指定范围内(这里用闭区间,你可以根据需求改成开闭) (array): array is t.Branded<t.TypeOf<T>[], MinMaxArrayBrand<T>> => array.length >= min && array.length <= max, // 品牌标识,用于错误提示的区分 'MinMaxArray' );
使用示例
这个函数完全通用,支持任意元素类型的数组校验,比如:
// 1. 创建一个长度在2-5之间的字符串数组校验器 const StringArray2To5 = minMaxArray(t.string, 2, 5); // 合法输入:返回Right结果 console.log(StringArray2To5.decode(['apple', 'banana', 'cherry'])); // Right(["apple", "banana", "cherry"]) // 非法输入(长度不足):返回Left错误 console.log(StringArray2To5.decode(['apple'])); // Left(...) 提示不符合MinMaxArray校验 // 2. 创建一个长度在1-3之间的数字数组校验器 const NumberArray1To3 = minMaxArray(t.number, 1, 3); // 合法输入 console.log(NumberArray1To3.decode([10, 20])); // Right([10, 20]) // 非法输入(长度超限) console.log(NumberArray1To3.decode([1, 2, 3, 4])); // Left(...)
可选优化:自定义错误提示
如果你想让错误信息更直观,可以结合t.refinement和品牌,或者使用io-ts的PathReporter来获取更清晰的错误描述,但上面的基础实现已经完全满足API端点的运行时验证需求。
内容的提问来源于stack exchange,提问作者Andras Hegedus
相关产品推荐
相关产品推荐

