export type ObjectValidator = { [key in keyof T]?: ParameterValidator; }; interface ParameterValidatorObject { default?: unknown; min?: number; max?: number; func?: (obj: Type, validator: ObjectValidator, key: Key) => void; } type ParameterValidatorFunction = (obj: Type, key: Key) => void; type ParameterValidator = | ParameterValidatorObject | ParameterValidatorFunction; export function validateObject, Key extends keyof Type>( obj: Type, validator: ObjectValidator, ): void { for (const key of Object.keys(validator) as Key[]) { const paramValidator = validator[key]; if (paramValidator !== undefined) { if (typeof paramValidator === "function") { paramValidator(obj, key); } else if (paramValidator.func !== undefined) { paramValidator.func(obj, validator, key); } else { const objVal = obj[key]; if (typeof objVal !== typeof paramValidator.default) { obj[key] = paramValidator.default as Type[Key]; } if (typeof objVal === "number" && paramValidator.min !== undefined && objVal < paramValidator.min) { obj[key] = paramValidator.min as Type[Key]; } if (typeof objVal === "number" && paramValidator.max !== undefined && objVal > paramValidator.max) { obj[key] = paramValidator.max as Type[Key]; } } } } } export function minMax( def: number, min: number, max: number, ): (obj: Type, key: Key & keyof Type) => void { return (obj, key) => { if (typeof obj[key] !== "number") { obj[key] = def as unknown as Type[Key]; return; } if ((obj[key] as unknown as number) < min) { obj[key] = min as unknown as Type[Key]; } if ((obj[key] as unknown as number) > max) { obj[key] = max as unknown as Type[Key]; } }; } export function oneOf( def: Value, options: Value[], ): (obj: Type, key: Key & keyof Type) => void { return (obj, key) => { if (typeof obj[key] !== typeof def) { obj[key] = def as unknown as Type[Key]; return; } if (!options.includes(obj[key] as unknown as Value)) { obj[key] = def as unknown as Type[Key]; } }; } export function subsetOf( options: Value[], ): (obj: Type, key: Key & keyof Type) => void { return (obj, key) => { if (typeof obj[key] !== "object" || !Array.isArray(obj[key])) { obj[key] = [] as unknown as Type[Key]; return; } const validValues: Value[] = []; for (const value of obj[key] as unknown as Value[]) { if (options.includes(value)) validValues.push(value); } obj[key] = validValues as unknown as Type[Key]; }; }