Skip to main content

🦩 Computed Types

Runtime validation types for TypeScript.

View On NPM Build Status Dependency Status Coverage Status License


Computed-Types (formerly: Funval) is a strongly-typed validation library that seamlessly validates runtime types with perfect synchronization to TypeScript types. Using only plain functions, computed-types knows how to validate your data and automatically generates TypeScript interfaces to reduce code duplications and complexity.

Main Features

  • Easy to Read - Uses runtime types like TypeScript (including string, number, boolean, etc…)
  • Reusable Interfaces - Create new validator using plain functions in seconds.
  • TypeScript Validation - Detect errors during compile time.
  • Function Composition - Pipe multiple validators to generate new ones.
  • Asynchronous & Synchronous Support - Automatically detected promises.
  • Pure Javascript - Also works without TypeScript.

Install

npm i computed-types

Usage

import Schema, { Type, string, number, array } from 'computed-types';

const UserSchema = {
 name: string.trim().normalize().between(3, 40).optional(),
 username: /^[a-z0-9]{3,10}$/,
 status: Schema.either('active' as 'active', 'suspended' as 'suspended'),
 items: array
   .of({
     id: string,
     amount: number.gte(1).integer(),
   })
   .min(1),
};
type User = Type<typeof UserSchema>;

const validator = Schema(UserSchema).destruct();

const [err, user] = validator({
  username: 'john1',
  // @ts-ignore Type '"unregistered"' is not assignable to type '"active" | "suspended"'.
  status: 'unregistered',
  items: [{ id: 'item-1', amount: 20 }],
});

console.log(err);
// TypeError: Expect value to equal "suspended" {
//   errors: [
//     {
//       error: TypeError: Expect value to equal "suspended",
//       path: ['status']
//     }
//   ]
// }

Creating new Types

A computed type is any function that can return a value without throwing any exceptions. For example this type will validate email addresses:

import * as EmailValidator from 'email-validator';

function Email(input: unknown): string {
  if (!EmailValidator.validate(String(input))) {
    throw new TypeError(`Invalid email address: "${input}"`);
  }

  return input;
}

Using the function interface, this type will receive any unknown value and try to convert it to a valid email address as a string. You can use the above validator on schemas as an Email type:

const UserSchema = {
  email: Email,
};

const validator = Schema(UserSchema);

Asynchronous Validators

Asynchronous validators are supported by returning a Promise (or PromiseLike) values:

import fetch from 'node-fetch';

async function AvailableUsername(input: string): Promise<string> {
  const res = await fetch(`/check-username?username=${encodeURIComponent(input)}`);

  if (!res.ok) {
    throw new TypeError(`Username "${input}" is already taken`);
  }

  return input;
}

Computed-types automatically detects promise and convert the return type of the Validator to promise as well:

const UserSchema = {
  username: AvailableUsername,
};
const validator = Schema(UserSchema);

const user = await validator({ username: 'test' });

License

MIT license © 2020 Neuledge