Security News
Supply Chain Attack Detected in Solana's web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
tcomb-validation
Advanced tools
tcomb-validation is a library for validating JavaScript values with static types. It provides a way to define types and validate data against those types, ensuring that your data conforms to the expected structure.
Type Definitions
You can define types using tcomb-validation. In this example, a 'Person' type is defined with 'name' as a string and 'age' as a number.
const t = require('tcomb-validation');
const Person = t.struct({
name: t.String,
age: t.Number
});
const person = Person({ name: 'John Doe', age: 30 });
Validation
tcomb-validation allows you to validate data against defined types. In this example, the validation fails because 'age' is a string instead of a number.
const t = require('tcomb-validation');
const Person = t.struct({
name: t.String,
age: t.Number
});
const result = t.validate({ name: 'John Doe', age: '30' }, Person);
console.log(result.isValid()); // false
Custom Types
You can create custom types using refinements. In this example, a 'Positive' type is defined to ensure the number is greater than zero.
const t = require('tcomb-validation');
const Positive = t.refinement(t.Number, n => n > 0, 'Positive');
const result = t.validate(10, Positive);
console.log(result.isValid()); // true
Joi is a powerful schema description language and data validator for JavaScript. It allows you to create blueprints or schemas for JavaScript objects to ensure validation. Compared to tcomb-validation, Joi offers a more extensive set of validation rules and is widely used in the Node.js community.
Yup is a JavaScript schema builder for value parsing and validation. It is similar to Joi but is often preferred for its simplicity and ease of use, especially in React applications. Yup provides a more modern API and better integration with form libraries like Formik.
AJV (Another JSON Schema Validator) is a JSON schema validator that is very fast and supports JSON Schema draft-07. It is more focused on JSON schema validation compared to tcomb-validation, which is more about type validation in JavaScript.
A general purpose JavaScript validation library based on type combinators
If you don't know how to define types with tcomb you may want to take a look at its README file.
The main function is validate
:
validate(value, type, [options]) -> ValidationResult
value
the value to validatetype
a type defined with the tcomb libraryoptions
(optional) is an object with the following keys
path: Array<string | number>
path prefix for validationcontext: any
passed to getValidationErrorMessage
(useful for i18n)strict: boolean
(default false
) if true
no additional properties are allowed while validating structsreturns a ValidationResult
object containing the result of the validation
Note.
options
can be an array (as path
prefix) for backward compatibility (deprecated)Example
var t = require('tcomb-validation');
var validate = t.validate;
validate(1, t.String).isValid(); // => false
validate('a', t.String).isValid(); // => true
You can inspect the result to quickly identify what's wrong:
var result = validate(1, t.String);
result.isValid(); // => false
result.firstError().message; // => 'Invalid value 1 supplied to String'
// see `result.errors` to inspect all errors
// null and undefined
validate('a', t.Nil).isValid(); // => false
validate(null, t.Nil).isValid(); // => true
validate(undefined, t.Nil).isValid(); // => true
// strings
validate(1, t.String).isValid(); // => false
validate('a', t.String).isValid(); // => true
// numbers
validate('a', t.Number).isValid(); // => false
validate(1, t.Number).isValid(); // => true
// booleans
validate(1, t.Boolean).isValid(); // => false
validate(true, t.Boolean).isValid(); // => true
// optional values
validate(null, maybe(t.String)).isValid(); // => true
validate('a', maybe(t.String)).isValid(); // => true
validate(1, maybe(t.String)).isValid(); // => false
// functions
validate(1, t.Function).isValid(); // => false
validate(function () {}, t.Function).isValid(); // => true
// dates
validate(1, t.Date).isValid(); // => false
validate(new Date(), t.Date).isValid(); // => true
// regexps
validate(1, t.RegExp).isValid(); // => false
validate(/^a/, t.RegExp).isValid(); // => true
You can express more fine-grained contraints with the refinement
syntax:
// a predicate is a function with signature: (x) -> boolean
var predicate = function (x) { return x >= 0; };
// a positive number
var Positive = t.refinement(t.Number, predicate);
validate(-1, Positive).isValid(); // => false
validate(1, Positive).isValid(); // => true
// an object with two numerical properties
var Point = t.struct({
x: t.Number,
y: t.Number
});
validate(null, Point).isValid(); // => false
validate({x: 0}, Point).isValid(); // => false, y is missing
validate({x: 0, y: 'a'}, Point).isValid(); // => false, y is not a number
validate({x: 0, y: 0}, Point).isValid(); // => true
validate({x: 0, y: 0, z: 0}, Point, { strict: true }).isValid(); // => false, no additional properties are allowed
Differences from structs
var Serializable = t.interface({
serialize: t.Function
});
validate(new Point(...), Serializable).isValid(); // => false
Point.prototype.serialize = function () { ... }
validate(new Point(...), Serializable).isValid(); // => true
Lists
// a list of strings
var Words = t.list(t.String);
validate(null, Words).isValid(); // => false
validate(['hello', 1], Words).isValid(); // => false, [1] is not a string
validate(['hello', 'world'], Words).isValid(); // => true
Tuples
// a tuple (width x height)
var Size = t.tuple([Positive, Positive]);
validate([1], Size).isValid(); // => false, height missing
validate([1, -1], Size).isValid(); // => false, bad height
validate([1, 2], Size).isValid(); // => true
var CssTextAlign = t.enums.of('left right center justify');
validate('bottom', CssTextAlign).isValid(); // => false
validate('left', CssTextAlign).isValid(); // => true
var CssLineHeight = t.union([t.Number, t.String]);
validate(null, CssLineHeight).isValid(); // => false
validate(1.4, CssLineHeight).isValid(); // => true
validate('1.2em', CssLineHeight).isValid(); // => true
// a dictionary of numbers
var Country = t.enums.of(['IT', 'US'], 'Country');
var Warranty = t.dict(Country, t.Number, 'Warranty');
validate(null, Warranty).isValid(); // => false
validate({a: 2}, Warranty).isValid(); // => false, ['a'] is not a Country
validate({US: 2, IT: 'a'}, Warranty).isValid(); // => false, ['IT'] is not a number
validate({US: 2, IT: 1}, Warranty).isValid(); // => true
var Min = t.refinement(t.String, function (s) { return s.length > 2; }, 'Min');
var Max = t.refinement(t.String, function (s) { return s.length < 5; }, 'Max');
var MinMax = t.intersection([Min, Max], 'MinMax');
MinMax.is('abc'); // => true
MinMax.is('a'); // => false
MinMax.is('abcde'); // => false
You can validate structures with an arbitrary level of nesting:
var Post = t.struct({
title: t.String,
content: t.String,
tags: Words
});
var mypost = {
title: 'Awesome!',
content: 'You can validate structures with arbitrary level of nesting',
tags: ['validation', 1] // <-- ouch!
};
validate(mypost, Post).isValid(); // => false
validate(mypost, Post).firstError().message; // => 'tags[1] is `1`, should be a `Str`'
You can customise the validation error message defining a function getValidationErrorMessage(value, path, context)
on the type constructor:
var ShortString = t.refinement(t.String, function (s) {
return s.length < 3;
});
ShortString.getValidationErrorMessage = function (value) {
if (!value) {
return 'Required';
}
if (value.length >= 3) {
return 'Too long my friend';
}
};
validate('abc', ShortString).firstError().message; // => 'Too long my friend'
In order to keep the validation logic in one place, one may define a custom combinator:
function mysubtype(type, getValidationErrorMessage, name) {
var Subtype = t.refinement(type, function (x) {
return !t.String.is(getValidationErrorMessage(x));
}, name);
Subtype.getValidationErrorMessage = getValidationErrorMessage;
return Subtype;
}
var ShortString = mysubtype(t.String, function (s) {
if (!s) {
return 'Required';
}
if (s.length >= 3) {
return 'Too long my friend';
}
});
Let's design the process for a simple sign in form:
var SignInInfo = t.struct({
username: t.String,
password: t.String
});
// retrieves values from the UI
var formValues = {
username: $('#username').val().trim() || null,
password: $('#password').val().trim() || null
};
// if formValues = {username: null, password: 'password'}
var result = validate(formValues, SignInInfo);
result.isValid(); // => false
result.firstError().message; // => 'Invalid value null supplied to /username: String'
If you don't want to use a JSON Schema validator or it's not applicable, you can just use this lightweight library in a snap. This is the JSON Schema example of http://jsonschemalint.com/
{
"type": "object",
"properties": {
"foo": {
"type": "number"
},
"bar": {
"type": "string",
"enum": [
"a",
"b",
"c"
]
}
}
}
and the equivalent tcomb-validation
counterpart:
var Schema = t.struct({
foo: t.Number,
bar: t.enums.of('a b c')
});
let's validate the example JSON:
var json = {
"foo": "this is a string, not a number",
"bar": "this is a string that isn't allowed"
};
validate(json, Schema).isValid(); // => false
// the returned errors are:
- Invalid value "this is a string, not a number" supplied to /foo: Number
- Invalid value "this is a string that isn't allowed" supplied to /bar: "a" | "b" | "c"
Note: A feature missing in standard JSON Schema is the powerful refinement syntax.
ValidationResult
represents the result of a validation. It containes the following fields:
errors
: a list of ValidationError
if validation failsvalue
: an instance of type
if validation succeded// the definition of `ValidationError`
var ValidationError = t.struct({
message: t.String, // a default message for developers
actual: t.Any, // the actual value being validated
expected: t.Function, // the type expected
path: list(t.union([t.String, t.Number])) // the path of the value
}, 'ValidationError');
// the definition of `ValidationResult`
var ValidationResult = t.struct({
errors: list(ValidationError),
value: t.Any
}, 'ValidationResult');
Returns true if there are no errors.
validate('a', t.String).isValid(); // => true
Returns an object that contains an error message or null
if validation succeeded.
validate(1, t.String).firstError().message; // => 'value is `1`, should be a `Str`'
value
the value to validatetype
a type defined with the tcomb libraryoptions
(optional) is an object with the following keys
path: Array<string | number>
path prefix for validationcontext: any
passed to getValidationErrorMessage
(useful for i18n)strict: boolean
(default false
) if true
no additional properties are allowed while validating structsRun npm test
The MIT License (MIT)
v3.4.1
FAQs
General purpose validation library for JavaScript
The npm package tcomb-validation receives a total of 1,058,658 weekly downloads. As such, tcomb-validation popularity was classified as popular.
We found that tcomb-validation demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.