Skip to main content
Deno 2 is finally here 🎉️
Learn more

🦩 Funval

A minimalist library for data validation using plain functions.

View On NPM Build Status Dependency Status License


Funval is a minimalist validation library that seamlessly integrates with your existing TypeScript schemas. Using only pure functions, Funval knows how to validate your data and automatically generates TypeScript interfaces to reduce code duplications and complexity.

declare function Validator<T, I>(input: I): T | Promise<T>;

Main Features

  • Asynchronous & Synchronous Support - Automaticly detected by validators types.
  • Pure Javascript - Works also without TypeScript.
  • Seamless Interfaces - Create new validator using plain functions in seconds.
  • Function Composition - Pipe multiple validators to generate new ones.
  • TypeScript Validation - Detect errors during compile time.

Install

npm i funval

Usage

import { Schema, Optional, Or, NonEmptyString, StringRange, Type } from 'funval';
import compose from 'compose-function';

const UserSchema = {
  name: Optional(String),
  username: compose(StringRange(3, 20), NonEmptyString),
  status: Or('active' as 'active', 'suspended' as 'suspended'),
  amount: Number,
};

const validator = Schema(UserSchema);

let user: Type<typeof UserSchema>;

try {
  user = validator({
    username: 'john1',
    // @ts-ignore Type '"unregistered"' is not assignable to type '"active" | "suspended"'.
    status: 'unregistered',
    amount: 20.3,
  });
} catch (err) {
  console.error(err.message, err.paths);
}

Creating Validators

A validator is any function that can return a value:

import * as EmailValidator from 'email-validator';

function Email(input: string): string {
  if (!EmailValidator.validate(input)) {
    throw new TypeError(`The given email "${input}" is invalid`);
  }

  return input;
}

You can use the Email validator on schemas by using:

const UserSchema = {
  email: Email,
};

const validator = Schema(UserSchema);

Asynchronous Validators

Asynchronous validators are supported by resolving to a Promise value:

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;
}

Funval automatically detects promise values and convert the return type of the Validator to promise as well:

const UserSchema = {
  username: AvailableUsername,
};

const validator = await Schema(UserSchema);

If you prefer, you can safely convert any validator to an asynchronous validator using the Async helper:

import { Async, Schema } from 'funval';

const UserSchema = {
  email: Email,
};

const validator = await Async(Schema(UserSchema));

License

MIT license © 2020 Neuledge