Skip to content
This repository was archived by the owner on Apr 8, 2022. It is now read-only.

Repository files navigation

Typesmith: Easy Runtime Validation

Typesmith logo

Inspired by typescript-is.

Transforms typescript interfaces, classes and other types into runtime validation functions. It leverages these fine libraries:

💿 Quick Start Guide

  1. Install typesmith

    npm i --save typesmith
  2. Install ttypescript

    npm i --save-dev ttypescript
  3. Edit your tsconfig.json to use the plugin

    {
    "compilerOptions": {
    "plugins": [{ "transform": "typesmith/transformer" }]
    }
    }
  4. Replace tsc ... commands with ttsc ... commands.

📐 Example

import{assertTypeFn,DateString}from"typesmith";interfacePerson{/** @minLength 1 */firstName: string;lastName: string;dateOfBirth: DateString;}constassertPerson=assertTypeFn<Person>();constjillSmith={firstName: "Jill",lastName: "Smith",dateOfBirth: "1990-12-31"};constjaneDoe={firstName: "Jane",lastName: "Doe",dateOfBirth: "1990-12-31"};constinvalidPerson={};// Validation Successful ResultassertPerson(jillSmith).isSuccess===true;assertPerson(jillSmith).unwrap()===jillSmith;assertPerson(jillSmith).getErrors()===null;assertPerson(jillSmith).getOrElse(janeDoe)===jillSmith;assertPerson(jillSmith).getOrElseL(errors=>janeDoe)===jillSmith;// Validation Failure ResultassertPerson(invalidPerson).isSuccess===false;assertPerson(invalidPerson).unwrap();// Throws ErrorassertPerson(invalidPerson).getErrors().length>0;assertPerson(invalidPerson).getOrElse(janeDoe)===janeDoe;assertPerson(invalidPerson).getOrElseL(errors=>janeDoe)===janeDoe;

🎛️ Options

  • allErrors: (default: true) returns all errors instead of returning only the first one
  • removeAdditional: (default: false) remove additional properties
  • useDefaults: (default: false) replace missing or undefined properties and items with the values from corresponding default keywords
  • coerceTypes: (default: false) change data type of data to match type keyword
  • lazyCompile: (default: true) wait to compile validation function until first use

Options are specifiable at the global and type level, EG:

import{assertTypeFn,settings,Validatable}from"typesmith";// Globally:settings.updateGlobalValidationOptions({removeAdditional: true});// Type-LevelassertTypeFn<{name: string}>({coerceTypes: true});
@Validatable({coerceTypes: true})classFoo{}

💣 Caveats

Compiler crashes in rare but specific circumstances:

  • Mixin classes:
    // Crashes
    @Validatable()exportclassPersonSearchRequestextendsSearchRequestOf(PersonFilters){}
  • Anonymous recursive generic types:
    // OkaytypeNumberBTree=BTree<number>;assertTypeFn<NumberBTree>();// (Works as of v0.9.8)assertTypeFn<BTree<number>>();

AJV's type coercion ineffective for primitives

With AJV's coerceTypes enabled, coerced primitives will validate but will return the original value. EG:

// Coercion of boxed value worksassertTypeFn<number>({value: "12"}).unwrap().value===12;// Coercion of primitive doesn'tassertTypeFn<number>("12").unwrap()==="12"

@Validate() w/ Generic Type Parameters

Defaults must be provided to classes with generic type paramters. EG:

// Okay
@Validate()classFoo<A=any>{}// Crashes
@Validate()classFoo<A>{}

Dates

TODO

note: try using { DateInstance, DateTimeFlex, DateTimeString } from "typesmith"

✔ Todo

Features

  • feat: allow strings to be coerced to other primitives without using AJV's built-in coercion since it is too lenient. EG, false shouldn't be coerced to 0
  • feat: use ajv-pack for precompiled validation functions. ajv-pack has restrictions so this would need to be optional.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages