validate-any

What is validate-any?
This package is a type validator mainly for Typescript (also works with Javascript). Ever faced those issues where
you're trying to make sure a type any is an instance of an interface? This is the issue this package was designed to
solve. With this package, you can safely assert the type for an object and return customised errors if the types are
incorrect
Installation & Usage
$ npm install validate-any
or
$ yarn add validate-any
then import the module like this:
import { validate } from "validate-any"
const { validate } = require("validate-any")
Typescript typings are automatically included so there's no need to install anything like @types/validate-any !
How the validate function works
The validate object we imported earlier is a function which can take 2 (3: optional) parameters.
validate parameters:
1 | any | The object we are checking |
2 | Validator | A specific rule to compare the object to (more about this later) |
3 | string? | The name of the root object when logs display errors. Defaults to * as root |
The type Validator is something you don't need to worry about. Just know that it is the Typescript type for a rule.
Rules can look like STRING() or NUMBER().
validate returns an object containing:
| success | boolean | Whether the validation of the object was a success or failure. true if success, false if failure |
| errors | iValidationError[] | The list of corrections to make if any |
| data | T | The data you passed in with type annotations from the schema you passed in |
iValidationError is the data type for an error
| location | string | Where in the object did an error occur. E.g. "* > settings > wallpaper" |
| message | string | Description of what the error is |
| expected | string | The expected type of value |
| value | T | The value given |
In the examples below, you will see in the error object I only show the error message and display a "..." after it.
This is because I don't want to display unnecessary information.
However, every single error will have all the properties defined here
Also do note that the location started with a *.
This is the name of the root defined here
Making a rule
There are infinite combinations of rules we can make. The complexity of the rule only depends on how much code you are
willing to write.
Validation basics with STRING()
Here is how to validate a string
console.log(validate("string", STRING()))
console.log(validate(0, STRING()))
The function STRING with nothing in the parameters represents a type string.
This method can also take in items in the parameters:
(empty) | validates if the input is a string |
RegExp | validates if the input is a string and matches the RegExp |
...string[] | validates if the input is a string and matches any of the given strings |
import { validate, STRING } from "validate-any"
console.log(validate("string", STRING()))
console.log(validate(0, STRING()))
console.log(validate("string", STRING(/^string$/)))
console.log(validate("string", STRING(/^something-else$/)))
console.log(validate("string", STRING("does", "the", "string", "match", "?")))
console.log(validate("string", STRING("doesn't", "match"), "my-string"))
Validating a number with NUMBER()
Because STRING() validates strings, it's obvious that NUMBER() validates numbers. NUMBER() works the same was as STRING() except allows a different set of parameters:
(empty) | validates if the input is a number |
...number[] | validates if the input is a number and matches any of the given numbers |
import { validate, NUMBER } from "validate-any"
console.log(validate(3, NUMBER()))
console.log(validate("string", NUMBER()))
console.log(validate(3, NUMBER(1, 2, 3, 4, 5)))
console.log(validate(3, NUMBER(6, 7, 8, 9, 10)))
Validating a boolean with BOOLEAN()
BOOLEAN() allows comparison of booleans only
(empty) | validates if the input is a boolean |
boolean | validates if the input is a boolean and if the booleans are equal |
import { validate, BOOLEAN } from "validate-any"
console.log(validate(true, BOOLEAN()))
console.log(validate("string", BOOLEAN()))
console.log(validate(true, BOOLEAN(true)))
console.log(validate(false, BOOLEAN(true)))
Validating null with NULL()
NULL() doesn't allow variations of the parameters
(empty) | validates if the input is a null |
import { validate, NULL } from "validate-any"
console.log(validate(null, NULL()))
console.log(validate(undefined, NULL()))
Validating undefined with UNDEFINED()
Just like NULL(), UNDEFINED() doesn't allow variations of the parameters
| (empty) | validates if the input is a undefined |
import { validate, UNDEFINED } from "validate-any"
console.log(validate(undefined, UNDEFINED()))
console.log(validate(null, UNDEFINED()))
Validating a list with LIST()
This one's a bit more complicated. LIST() allows a few sets of parameters:
(empty) | validates if the input is a list |
...Validator[] | validates if the input is a list and checks if all items in the list match at least 1 of the Rules stated |
import { validate, LIST, STRING, NUMBER } from "validate-any"
console.log(validate([1, 2, 3, 4, 5], LIST()))
console.log(validate({ property: "value" }, LIST()))
console.log(validate(["one", "two", "three"], LIST(STRING())))
console.log(validate([1, "two", 3], LIST(NUMBER())))
console.log(validate([1, "two", []], LIST(STRING(), NUMBER(), LIST())))
console.log(validate([1, "two", null], LIST(STRING(), NUMBER())))
const usernames = ["jack", "_jack", "-jack"]
console.log(validate(usernames, LIST(STRING(/^[a-zA-Z]/))))
const codes = [34, 76, 92]
console.log(validate(codes, LIST(NUMBER(34, 76, 92))))
This way, we can make checking of list types much more detailed
Validating an object with OBJECT()
We can use OBJECT() to validate objects.
OBJECT() only allows 1 optional parameter which maps out what the properties will look like
import { validate, OBJECT } from "validate-any"
console.log(validate({ property: "value" }, OBJECT()))
console.log(validate({ property: "value" }, OBJECT({})))
console.log(validate({ property: "value" }, OBJECT({ property: STRING() })))
console.log(
validate(
{
property: "value"
},
OBJECT({
prop: STRING()
})
)
)
console.log(
validate(
{
property: "value",
layer: {
deepProperty: ["", 0, null, undefined, false]
}
},
OBJECT({
property: STRING(),
layer: OBJECT({
deepProperty: LIST(
STRING(),
NUMBER(0),
NULL(),
UNDEFINED(),
BOOLEAN(false)
)
})
})
)
)
Validating the or operation with OR()
If you want either of a few rules to match, use the OR() operator. This function takes multiple parameters:
...Validator[] | A list of rules to test on the input |
import { validate, OR, STRING, NUMBER, BOOLEAN } from "validate-any"
console.log(validate("string", OR()))
console.log(validate("string", OR(STRING(), NUMBER())))
console.log(validate("string", OR(BOOLEAN(), NUMBER())))
Using withValidBody with a Express or Next
You can also import the module as a middleware to be used with Express or Next.
This way, you can verify the types of the req.body before invalid types mess your code up
import { OBJECT, STRING, withValidBody } from "validate-any"
app.post(
"/body",
withValidBody(OBJECT({ usnm: STRING(), pswd: STRING() }), (req, res) => {
const { usnm, pswd } = req.body
console.log(`Username: ${usnm}`, `Password: ${pswd}`)
res.end()
})
)
export default withValidBody(
OBJECT({ usnm: STRING(), pswd: STRING() }),
(req, res) => {
const { usnm, pswd } = req.body
console.log(`Username: ${usnm}`, `Password: ${pswd}`)
res.end()
}
)
The withValidBody takes in 2 parameters:
1 | Validator | Rule to compare the req.body with |
2 | handler | Handler to handle the request if it works |
Because of the middleware, in Typescript you can now safely use type assertions.
Also, now for both Typescript and Javascript, you can safely use the variables like
they are the defined types and not have to worry about invalid types crashing your server!