如何使用io-ts验证数组长度? [英] How to validate array length with io-ts?
问题描述
我正在进行 io-ts 验证,我想验证列表长度(必须在最小和最大之间).我想知道是否有一种方法可以实现此行为,因为在运行时可以很方便地进行API端点验证.
I am working on an io-ts validation where I would like to validate the list length (it has to be between min and max). I am wondering if there's a way to achieve this behavior since it could come quite handy at runtime for API endpoint validation.
到目前为止,我是
interface IMinMaxArray {
readonly minMaxArray: unique symbol // use `unique symbol` here to ensure uniqueness across modules / packages
}
const minMaxArray = (min: number, max: number) => t.brand(
t.array,
(n: Array): n is t.Branded<Array, IMinMaxArray> => min < n.length && n.length < max,
'minMaxArray'
);
上面的代码不起作用,它需要 Array
-s的参数,并且也不接受 t.array
.我该如何以通用方式进行这项工作?
The code above does not work, it requires an argument for the Array
-s and t.array
is also not accepted. How could I make this work in a generic way?
推荐答案
您的定义缺少数组的类型和编解码器.您可以对接口定义进行一些修改,并使用编解码器扩展品牌类型,从而完成这项工作:
Your definition is missing the typing and the codec for the array. You could make this work with a few modifications on the interface definition and extending the branded type with a codec:
interface IMinMaxArray<T> extends Array<T> {
readonly minMaxArray: unique symbol
}
const minMaxArray = <C extends t.Mixed>(min: number, max: number, a: C) => t.brand(
t.array(a),
(n: Array<C>): n is t.Branded<Array<C>, IMinMaxArray<C>> => min < n.length && n.length < max,
'minMaxArray'
);
现在您可以创建类似的定义
Now you can create a definition like
minMaxArray(3,5, t.number)
如果您希望定义更加通用和可组合,则可以编写一个接受谓词的通用品牌类型:
If you want the definition to be more generic and composable, you could write a generic branded type that accepts a predicate:
interface RestrictedArray<T> extends Array<T> {
readonly restrictedArray: unique symbol
}
const restrictedArray = <C>(predicate: Refinement<C[], ArrayOfLength<C>>) => <C extends t.Mixed>(a: C) => t.brand(
t.array(a), // a codec representing the type to be refined
(n): n is t.Branded<C[], RestrictedArray<C>> => predicate(n), // a custom type guard using the build-in helper `Branded`
'restrictedArray' // the name must match the readonly field in the brand
)
interface IRestrictedArrayPredicate<C extends t.Mixed> {
(array: C[]): array is ArrayOfLength<C>
}
现在您可以定义限制.分别定义min和max可能是一个好主意,因为它们也可以单独使用:
Now you can define your restrictions. It's probably a good idea to define min and max separately, since they can be useful on their own too:
const minArray = <C extends t.Mixed>(min: number)
=> restrictedArray(<IRestrictedArrayPredicate<C>>((array) => array.length >= min));
const maxArray = <C extends t.Mixed>(max: number)
=> restrictedArray(<IRestrictedArrayPredicate<C>>((array) => array.length <= max));
将这两者结合起来可以定义minMaxArray:
And combining these two you can define minMaxArray:
export const minMaxArray = <C extends t.Mixed>(min: number, max: number, a: C) => t.intersection([minArray(min)(a), maxArray(max)(a)])
希望这会有所帮助.
这篇关于如何使用io-ts验证数组长度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!