Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement object validation using TypeScript?

I have an Express API server app and a React client app both implemented in TypeScript. I defined my data models using TypeScript interfaces, and I'm using those interfaces on both ends of the system. However, TypeScript interfaces are compile-time feature only, and I need also runtime type checking, e.g. validating that HTTP POST data (json) conforms to the defined data structure.

So my question is, how could/should I implement runtime object validation utilizing the features provided by TypeScript?

like image 289
Kitanotori Avatar asked Jun 01 '17 02:06

Kitanotori


2 Answers

I've created a super lightweight library called Smoke Screen which does exactly that. It leverages typescript features to perform any kind of object validation within javascript runtime. It's not 100% seamless due to the fact that javascript does not hold any type information at runtime, but thanks to TypeScript decorators, this may be easily done:

class Person {

    @exposed({type: Number})
    age: number;

}

// serialize a Person object into a JSON string
const person = new Person();
person.age = 56.8;
const smokeScreen = new SmokeScreen();
smokeScreen.toJSON(person); // -> '{"age":56.8}'

// deserialize a JSON string into a Person object
let json = JSON.stringify({age: 19});
const person2 = smokeScreen.fromJSON(json, Person);
console.log(person2); // -> Person { age: 19 }

// typing validation
json = JSON.stringify({age: "oops"});
smokeScreen.fromJSON(json, Person); // Error: illegal input - property 'age' must be a number

Additional custom validators may be set, optional parameters and null checking are also supported and enforced. I suggest reading more about it and trying it out.

like image 50
Aviv Carmi Avatar answered Oct 20 '22 15:10

Aviv Carmi


This question is old, but I'd like to share my validation library also.

It's type-script friendly, tiny (no tons of unnecessary functionality) and easily extensible by custom validators.

npm: https://www.npmjs.com/package/checkeasy

github: https://github.com/smbwain/checkeasy

import {alternatives, arrayOf, int, object, oneOf, optional, string} from 'checkeasy';

const myValidator = object({
   a: int({max: 5}),
   b: string(),
   c: optional(float()),
   d: oneOf(['a', 'b', 7] as const),
   e: alternatives([string(), int()]),
   f: arrayOf(string()),
   g: object({
       subP: string(),
   }),
});

const value = myValidator(anyUnsafeData, 'name');
// type of value is: {
//    a: number,
//    b: string,
//    c: number | undefined,
//    d: "a" | "b" | 7,
//    e: string | number,
//    f: string[],
//    g: {subP: string},
//}

It also throws clear human readable messages in errors. E.g.

myValidator({a: 'hello'}, 'data');
// throws: [data.a] should be an integer

myValidator({a: 1, b: 'string', d: 'a', e: true}, 'data');
// throws: All alternatives failed for [data.e]:
//      [data.e.@alternative(0)] should be a string
//      [data.e.@alternative(1)] should be an integer
like image 29
Roman D Avatar answered Oct 20 '22 17:10

Roman D