0.9.8 • Published 4 years ago

typesmith v0.9.8

Weekly downloads
3
License
MIT
Repository
github
Last release
4 years ago

Typesmith: Easy Runtime Validation

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", "after": true }]
      }
    }
  4. Replace tsc ... commands with ttsc ... commands.

📐 Example

import { assertTypeFn, DateString } from "typesmith";

interface Person {
  /** @minLength 1 */
  firstName: string;
  lastName: string;
  dateOfBirth: DateString;
}

const assertPerson = assertTypeFn<Person>();

const jillSmith = { firstName: "Jill", lastName: "Smith", dateOfBirth: "1990-12-31" };
const janeDoe = { firstName: "Jane", lastName: "Doe", dateOfBirth: "1990-12-31" };
const invalidPerson = {};

// Validation Successful Result
assertPerson(jillSmith).isSuccess === true;
assertPerson(jillSmith).unwrap() === jillSmith;
assertPerson(jillSmith).getErrors() === null;
assertPerson(jillSmith).getOrElse(janeDoe) === jillSmith;
assertPerson(jillSmith).getOrElseL(errors => janeDoe) === jillSmith;

// Validation Failure Result
assertPerson(invalidPerson).isSuccess === false;
assertPerson(invalidPerson).unwrap(); // Throws Error
assertPerson(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-Level
assertTypeFn<{ name: string }>({ coerceTypes: true });
@Validatable({ coerceTypes: true }) class Foo {}

💣 Caveats

Compiler crashes in rare but specific circumstances:

  • Mixin classes:
    // Crashes
    @Validatable()
    export class PersonSearchRequest extends SearchRequestOf(PersonFilters) {}
  • Anonymous recursive generic types:

    // Okay
    type NumberBTree = 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 works
assertTypeFn<number>({value: "12"}).unwrap().value === 12;
// Coercion of primitive doesn't
assertTypeFn<number>("12").unwrap() === "12"

@Validate() w/ Generic Type Parameters

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

// Okay
@Validate() class Foo<A = any> {}

// Crashes
@Validate() class Foo<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.
0.10.0-rc.2

4 years ago

0.10.0-rc.1

4 years ago

0.10.0-rc.0

4 years ago

0.9.8

5 years ago

0.9.7

5 years ago

0.9.6

5 years ago

0.9.5

5 years ago

0.9.4

5 years ago

0.9.3

5 years ago

0.9.2

5 years ago

0.9.1

5 years ago

0.9.0

5 years ago

0.8.7

5 years ago

0.8.6

5 years ago

0.8.5

5 years ago

0.8.4

5 years ago

0.8.3

5 years ago

0.8.2

5 years ago

0.8.1

5 years ago

0.8.0

5 years ago

0.7.0

5 years ago

0.6.0

5 years ago

0.5.0

5 years ago

0.4.0

5 years ago

0.3.1

5 years ago

0.2.2

5 years ago

0.2.0

5 years ago