简体   繁体   English

如何使用io-ts验证数组长度?

[英]How to validate array length with io-ts?

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).我正在进行io-ts验证,我想验证列表长度(它必须在最小和最大之间)。 I am wondering if there's a way to achieve this behavior since it could come quite handy at runtime for API endpoint validation.我想知道是否有办法实现这种行为,因为它可以在运行时非常方便地进行 API 端点验证。

What I have so far is到目前为止我所拥有的是

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'
);

The code above does not work, it requires an argument for the Array -s and t.array is also not accepted.上面的代码不起作用,它需要Array -s 的参数,并且t.array也不被接受。 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>
}

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:分别定义 min 和 max 可能是个好主意,因为它们本身也很有用:

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));

And combining these two you can define minMaxArray:结合这两者,您可以定义 minMaxArray:

export const minMaxArray = <C extends t.Mixed>(min: number, max: number, a: C) => t.intersection([minArray(min)(a), maxArray(max)(a)])

Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM