import * as NumberCheck from "./number"; import * as FunctionCheck from "./function"; export enum ArrayLikeErrorCode { IS_NULL = "IS_NULL", IS_UNDEFINED = "IS_UNDEFINED", NO_LENGTH_PROPERTY = "NO_LENGTH_PROPERTY", NO_INDEX_OF_PROPERTY = "NO_INDEX_OF_PROPERTY" } export type ArrayLikeErrorCodeType = ( ArrayLikeErrorCode| { index : number|string, error : ( NumberCheck.NaturalNumberErrorCodeType| FunctionCheck.FunctionErrorCode ) } ); export function checkArrayLike (mixed : any) : undefined|ArrayLikeErrorCodeType { if (mixed === null) { return ArrayLikeErrorCode.IS_NULL; } if (mixed === undefined) { return ArrayLikeErrorCode.IS_UNDEFINED; } if (!mixed.hasOwnProperty("length")) { return ArrayLikeErrorCode.NO_LENGTH_PROPERTY; } { const lengthValue = (mixed as any).length; const error = NumberCheck.checkNaturalNumber(lengthValue); if (error !== undefined) { return { index : "length", error : error }; } } { const indexOf = (mixed as any).indexOf; if (indexOf == null) { return ArrayLikeErrorCode.NO_INDEX_OF_PROPERTY; } const error = FunctionCheck.checkFunction(indexOf); if (error !== undefined) { return { index : "indexOf", error : error }; } } return undefined; } export function checkArrayLikePredicate (mixed : any, predicate : (arr : { [index : number] : any, length : number, indexOf : (item : any) => number }) => undefined|ErrorCodeT) : undefined|ArrayLikeErrorCodeType|ErrorCodeT { const error = checkArrayLike(mixed); if (error !== undefined) { return error; } return predicate(mixed); } export enum MinLengthErrorCode { SHORTER_THAN_MIN = "SHORTER_THAN_MIN" } export type MinLengthErrorCodeType = ArrayLikeErrorCodeType|MinLengthErrorCode; export function checkMinLength (mixed : any, min : number) : undefined|MinLengthErrorCodeType { return checkArrayLikePredicate(mixed, (arr) => { if (arr.length < min) { return MinLengthErrorCode.SHORTER_THAN_MIN; } else { return undefined; } }); } export enum MaxLengthErrorCode { LONGER_THAN_MAX = "LONGER_THAN_MAX" } export type MaxLengthErrorCodeType = ArrayLikeErrorCodeType|MaxLengthErrorCode; export function checkMaxLength (mixed : any, max : number) : undefined|MaxLengthErrorCodeType { return checkArrayLikePredicate(mixed, (arr) => { if (arr.length > max) { return MaxLengthErrorCode.LONGER_THAN_MAX; } else { return undefined; } }); } export type LengthErrorCodeType = { forcedArg : any, error : MinLengthErrorCodeType|MaxLengthErrorCodeType }; export function checkLength (mixed : any, args : { min? : number, max? : number }) : undefined|LengthErrorCodeType { if (args.min != null) { const error = checkMinLength(mixed, args.min); if (error !== undefined) { return { forcedArg : args.min, error : error }; } } if (args.max != null) { const error = checkMaxLength(mixed, args.max); if (error !== undefined) { return { forcedArg : args.max, error : error }; } } return undefined; } export enum NonEmptyErrorCode { IS_EMPTY = "IS_EMPTY" } export type NonEmptyErrorCodeType = ArrayLikeErrorCodeType|NonEmptyErrorCode; export function checkNonEmpty (mixed : any) : undefined|NonEmptyErrorCodeType { return checkArrayLikePredicate(mixed, (arr) => { if (arr.length == 0) { return NonEmptyErrorCode.IS_EMPTY; } else { return undefined; } }); } export enum ContainsErrorCode { DOES_NOT_CONTAIN = "DOES_NOT_CONTAIN" } export type ContainsErrorCodeType = ArrayLikeErrorCodeType|ContainsErrorCode; export function checkContains (mixed : any, x : any) : undefined|ContainsErrorCodeType { return checkArrayLikePredicate(mixed, (arr) => { if (arr.indexOf(x) < 0) { return ContainsErrorCode.DOES_NOT_CONTAIN; } else { return undefined; } }); } export enum NoDuplicateErrorCode { IS_DUPLICATE = "IS_DUPLICATE" } export type NoDuplicateErrorCodeType = ( ArrayLikeErrorCodeType | { index : number|string, error : NoDuplicateErrorCode.IS_DUPLICATE } ); /* Uses strict comparison. So, the array-like could contain both `null` and `undefined`! */ export function checkNoDuplicate (mixed : any) : undefined|NoDuplicateErrorCodeType { return checkArrayLikePredicate(mixed, (arr) => { for (let i=0; i