Utility for Typescript projects that allows to check that an object validates a predefined contract.
To install the type checker for use in your project, go to your project's main directory, then run the following command:
npm install --production --save node-typechecker
To use the type checker in your project, follow the snippet below:
The node-typechecker type definitions are included in the npm package.
Important! Node typechecker requires TypeScript >= 1.8 and the experimentalDecorators
and emitDecoratorMetadata
options in your tsconfig.json file.
{
"compilerOptions": {
... // Other options you need
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
You need to add validation in your classes using the PropertyCheck
decorator.
The PropertyCheck
decorator takes an optional parameter in its constructor, with the following structure:
{
type?: any; // Used to override a property type (if you don't include this parameter, property type will be automatically found)
required?: boolean; // Tell the validator if the property is required (default to true)
nullable?: boolean; // Tell the validator if the property can be null or undefined (default false)
arrayType?: any; // If your property is an array, define the item's type. If you don't want to check the item's type, just omit this parameter (default undefined)
onFailure?: 'ignore'|'setNull' // Tell the validator to ignore the validation failures for the given property. The value will either be set to "null" or ignored in the resulting parsed object, according to the "onFailure" parameter (default: always throws errors)
customValidator?: (input: any) => boolean; // If present, will perform a custom validation on the property. The custom validation is only executed if the "basic" validations (required, nullable) are successful.
}
Let's take an example with an Article
class:
File Article.ts:
// Import module
import {PropertyCheck} from 'node-typechecker';
import {Author} from './Author.ts'; // Existing Author class which also contains validation
export class Article {
// Property title is required and non-nullable (default behavior)
@PropertyCheck()
public title: string;
// Property subTitle is not required, but if present it is non-nullable
@PropertyCheck({required: false})
public subTitle: string;
// As there is no PropertyCheck decorator, property content will be ignored by the Type checker
public content: string;
// Property tags is required but its value is non-nullable, if present, tags items will not be checked
@PropertyCheck({nullable: true})
public tags: string[];
// Property authors is required, non-nullable, and its children will be checked as Author objects
// If Author class uses PropertyCheck decorators, nested validation will be performed
@PropertyCheck({arrayType: Author})
public authors: Author[];
}
You can validate objects with 2 different ways:
- Manual validation
- Automatic validation on function call
To validate an object manually, you can call the validate
method:
/**
* @param input Object to validate
* @param expectedType Expected type
* @param arrayType If input is an array, type of its items
*/
validate(input: any, expectedType: any, arrayType?: any): void
This method throws a ValidationError
if validation fails, and returns an instance of the validated object on success.
For example, using the previously created Article
class:
import {validate} from 'node-typechecker';
import {Article} from './Article.ts';
const article = new Article();
article.title = 'title';
// In this case, the validate() method will throw a ValidationError because the Article 'tags' property is required
validate(article, Article);
// On success, the validate() method will automatically create a valid instance of Article, for example:
const data: any = {
title: 'Title',
content: 'Content',
tags: [],
authors: []
};
const result = validate(data, Article);
// 'result' is now a valid instance of Article object
You can perform an automatic validation on function call, using the TypesCheck
and TypeCheck
decorators.
The example below shows how to proceed:
import {TypesCheck, TypeCheck} from 'node-typechecker';
import {Article} from './Article';
@TypesCheck
function saveArticleInDb(@TypeCheck(Article) article: Article): void {
// If you reach this part, the input object is validated, save the article in database
}
const article = new Article();
article.title = 'title';
// In this case, saveArticleInDb() method will throw the ValidationError
saveArticleInDb(article);
In the previous example, as saveArticleInDb()
method uses the TypesCheck
and TypeCheck
decorators, the validatation will be called before the function execution, and the saveArticleInDb()
method will throw a ValidationError
.
- The
TypesCheck
decorator is needed to enable validation before function calls, and doesn't take any argument. - The
TypeCheck
decorator must be used for each parameter that needs validation, it takes one parameter which is the expected type.
As this module uses Typescript decorators which are a recent functionality, there are some limitations in its usage:
-
The class properties that can be validated have to be real objects (meaning: can be instanciated with the
new
operator):
For example, if a class property to validate is an interface orany
, the nested validation will be ignored (but therequired
andnullable
validations will still work). -
To validate array items type, you must use the
arrayType
parameter. Indeed thereflect-metadata
package that this modules uses can automatically detect base types, but typed arrays are detected asArray
.
- Rémy Jeancolas - Initial work - RemyJeancolas
This project is licensed under the MIT License - see the LICENSE.md file for details.