[英]How to validate array length with io-ts?
我正在進行io-ts驗證,我想驗證列表長度(它必須在最小和最大之間)。 我想知道是否有辦法實現這種行為,因為它可以在運行時非常方便地進行 API 端點驗證。
到目前為止我所擁有的是
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
也不被接受。 我怎樣才能以通用的方式使這項工作?
您的定義缺少數組的類型和編解碼器。 您可以通過對接口定義進行一些修改並使用編解碼器擴展品牌類型來完成這項工作:
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'
);
現在您可以創建一個定義,如
minMaxArray(3,5, t.number)
如果您希望定義更加通用和可組合,您可以編寫一個接受謂詞的通用品牌類型:
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 可能是個好主意,因為它們本身也很有用:
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:
export const minMaxArray = <C extends t.Mixed>(min: number, max: number, a: C) => t.intersection([minArray(min)(a), maxArray(max)(a)])
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.