@nonamenpm/type-validate
v1.0.1
Published
Validate object following predetermined rules.
Downloads
1
Maintainers
Readme
Use case
Runtime type validation is usually preferred when using config files for a program, to check if the user-supplied data is valid, or, when making tests, you want to check the structure of a given object, without actually having pre-determined values.
Example
The following program uses an example config for VSCode's jsconfig.json
config file, and provides an hypothetical rule to validate it.
// config.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6"
},
"include": ["src/**/*"]
}
// index.ts
import validate, { Optional, StringType, Branch, ArrayOf, Choice } from 'type-validate'
import { readFileSync } from 'fs'
// taking in consideration only `compilerOptions` and `include`
const rule = {
compilerOptions: Optional(Branch({
module: Optional(Choice('amd', 'commonJS', 'es2015', 'es6', 'esnext', 'none', 'system', 'umd')),
target: Optional(Choice('es3', 'es5', 'es6', 'es2015', 'es2015', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext'))
}))
include: Optional(ArrayOf(StringType))
}
validate(rule, JSON.parse(readFileSync('config.json'))) // in this case, everything is valid, and the function does not throw
Usage
validate<T extends ValidationRule>(rules: Record<string, ValidationRuleConstructor<T>>, toValidate: Record<string, unknown>): never | void
Takes a set of "type rules" and compares them to the input given to the function, when the input doesn't validate, this function throws a ValidationError
containing the expected type along with the key in the object that failed.
Example
import validate, {
StringType,
NumberType,
BooleanType,
ObjectType,
Optional,
} from 'type-validate';
const rules = {
name: StringType,
age: Optional(NumberType),
married: BooleanType,
additionalInfo: Optional(ObjectType),
};
validate(rules, { name: 'Foo', married: false }); // => doesn't throw, no rules were violated
validate(rules, { name: {}, age: 42, married: false, additionalInfo: {} }); // => throws, `name` is not a `string`
validate(rules, { age: 42, additionalInfo: {} }); // => throws, `name` and `married` aren't `Optional`
Any
Wildcard rule that accepts everything.
AnyOf
Accepts multiple rules as an input, returns true if at least one of the rules validates.
Example
validate({ example: AnyOf(StringType, NumberType) }, { example: 'foo' }); // => valid
validate({ example: AnyOf(StringType, NumberType) }, { example: 42 }); // => valid
validate({ example: AnyOf(StringType, NumberType) }, { exmple: true }); // => invalid, because we don't accept `BooleanType`
None
Accepts only undefined
Not
Negates the supplied rule
Example
validate({ example: Not(StringType) }, { example: 42 }); // => valid
validate({ example: Not(StringType) }, { example: true }); // => valid
validate({ example: Not(StringType) }, { example: undefined }); // => valid
validate({ example: Not(StringType) }, { example: 'foo' }); // => invalid, we do not accept `StringType`
ArrayOf
Validates any array that has every element that follows at least 1 rule.
Example
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: ['foo', 42] }
); // => valid
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: [true] }
); // => valid
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: [] }
); // => valid
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: [{}] }
); // => invalid, we don't accept `ObjectType`
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: undefined }
); // => invalid, the array is not `Optional`
ArrayStrict
Validates an array only if it follows the same structure as the rule.
Example
validate(
{ example: ArrayStrict(StringType, NumberType) },
{ example: ['foo', 42] }
); // => valid
validate(
{ example: ArrayStrict(StringType, NumberType) },
{ example: ['foo'] }
); // => invalid, missing `NumberType`
validate({ example: ArrayStrict(StringType, NumberType) }, { example: [42] }); // => invalid, missing `StringType`
validate(
{ example: ArrayStrict(StringType, NumberType) },
{ example: [42, 'foo'] }
); // => invalid, the order of the elements is reversed
validate({ example: ArrayStrict(StringType, NumberType) }, { example: [] }); // => invalid, array is empty
validate(
{ example: ArrayStrict(StringType, NumberType) },
{ example: ['foo', 42, 43] }
); // => invalid, does not follow the structure of the rule
Branch
Validates an object.
Example
validate({ example: Branch({ example2: Not(None) })) }, { example: { example2: 42 } }) // => valid
validate({ example: Branch({ example2: Not(None) })) }, { example: {} }) // => invalid, example2 is undefined (NOTE: if example2 was accepting `Any`, this example would be valid)
validate({ example: Branch({ example2: Not(None) })) }, { example: [] }) // => invalid, example is not an object
Optional
Makes the supplied rule optional.
import validate, { Optional, NumberType } from 'type-validate';
const rule = {
age: Optional(NumberType),
};
validate(rule, {}); // => valid
validate(rule, { age: 27 }); // => valid
validate(rule, { age: '27' }); // => invalid
Choice
Takes multiple arguments as choices, throws when the value in the object isn't present in Choice
.
Example
import validateRc, {
StringType,
NumberType,
BooleanType,
None,
Optional,
Choice,
} from 'validate-rc';
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: ['foo', 42] }
); // => valid
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: [true] }
); // => valid
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: [] }
); // => valid
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: [{}] }
); // => invalid, we don't accept `ObjectType`
validate(
{ example: ArrayOf(StringType, NumberType, BooleanType, None) },
{ example: undefined }
); // => invalid, the array is not `Optional`
Handling Errors
validate
throws a ValidationError
when the object given doesn't match the rule. It contains what it expected and the key that contains the invalid data.
Handling example
import validate, { ValidationError } from 'type-validate';
const rule = {
/* rules */
};
const config = require(process.cwd() + '/.dummyrc.js');
try {
validate(rule, config);
} catch (e) {
if (e instanceof ValidationError) {
console.log(`Expected type '${e.expected}' at '${e.key}'`);
process.exit(1);
} else throw e;
}