Giter Club home page Giter Club logo

rtti's Introduction

rtti

Runtime type validation for JavaScript and TypeScript programs.

This library bring the benefits of TypeScript's type system to runtime code. By declaring types using runtime constructs, it is possible to add an extra level of runtime type safety that static checking alone cannot provide. For example:

  • ensure that a parsed JSON string produces a value that conforms to an expected schema
  • verify that a HTTP request body conforms to an expected schema
  • ensure that a HTTP response body does not send additional properties other that those intended for the client

There is no need to declare any type twice (i.e., once for JS and once TS), since the TypeScript type can be inferred from the example property of any given TypeInfo value.

Installation

npm install rtti

Usage Example

import {t} from 'rtti';

const myType = t.union(
    t.unit('foo'),
    t.unit('bar')
);

// prints: "foo" | "bar"
console.log(myType.toString());

// prints: true
console.log(myType.isValid('foo'));

// prints: false
console.log(myType.isValid('baz'));

// prints: {
//     isValid: false,
//     errors: [
//         {path: '^', message: 'The value "baz" does not conform to the union type'}
//     ]
// }
console.log(myType.check('baz'));

// TypeScript only - static type inference:
type MyType = typeof myType.example; // type MyType = "foo" | "bar"

API

NOTE: The v0.4 API is deprecated but still supported.


t.string, t.object(...), etc

Construct a TypeInfo instance that matches a particular set of runtime values.


myType.assertValid(value: unknown): void

Ensures the given value matches the given type, otherwise throws an error. The error object has an errors property containing details about the validation error(s).


myType.check(value: unknown): {isValid: boolean, errors: Array<{path: string, message: string}>}

Returns a list of descriptive validation errors explaining why the given value does not match the given type.


myType.example

An example value that conforms to the given TypeInfo type. The TypeScript type can be inferred from this property.


myType.isValid(value: unknown): boolean

Returns true if the given value matches the given type, or false otherwise.


myType.sanitize(value: typeof myType.example): typeof myType.example

Returns a copy of the given value, but where any properties not declared in type have been removed.


myType.toJsonSchema(type: TypeInfo): unknown

Returns a JSON schema representation of the given type.


myType.toString(): string

Returns a descriptive string for the given type.


TypeInfo

An object used by the RTTI library to describes a set of matching runtime values. These objects may be created using the t.<kind> syntax. See the following table for examples.

Supported Types

PRIMITIVE JAVASCRIPT TYPES
Datatype Example RTTI Declaration TS Type Matching JS Values Non-Matching JS Values
Boolean t.boolean boolean true, false 0, '', 'yes', null
Date t.date Date new Date() '2020-01-01'
Null t.null null null undefined, 0
Number t.number number 42, 3.14 'three', false
String t.string string 'foo', '1:1' 42, {foo: 1}
Undefined t.undefined undefined undefined null, 0
COMPOUND JAVASCRIPT TYPES
Datatype Example RTTI Declaration TS Type Matching JS Values Non-Matching JS Values
Array t.array(t.number) number[] [1, 2, 3] 123, [1, 'a']
Object t.object({foo: t.string, isBar: t.optional(t.boolean)}) {foo: string, isBar?: boolean} {foo: 'foo'}, {foo: 'x', isBar: true} {bar: 'bar'}, {foo: true}
ADDITIONAL TYPESCRIPT TYPES
Datatype Example RTTI Declaration TS Type Matching JS Values Non-Matching JS Values
Any t.any any 42, 'foo', null, [1, 2], {} -
Branded String t.brandedString('usd')
Intersection t.intersection(t.object({foo: t.string}), t.object({bar: t.number})) {foo: string} & {bar: number} {foo: 'abc', bar: 42} {bar: 42}
Never t.never never - 42, 'foo', null, [1, 2], {}
Tuple t.tuple(t.string, t.number) [string, number] ['foo', 42] ['foo'], ['foo', 'bar'], ['foo', 4, 2]
Union t.union(t.object({foo: t.string}), t.object({bar: t.number})) `{foo: string} {bar: number}` {foo: 'abc'}, {bar: 42}
Unit Type t.unit('foo') 'foo' 'foo' 'bar', 'abc', 42
Unknown t.unknown 42, 'foo', null, [1, 2], {} -

rtti's People

Contributors

dependabot[bot] avatar yortus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

troyvgw

rtti's Issues

[BUG] removeExcessProperties doesn't work properly for nested intersections

Code ref: https://github.com/yortus/rtti/blob/master/src/remove-excess-properties.ts#L32-L36

If t contains members that are themselves intersections, then those intersections' members should also end up in combinedProps, but with this code they don't. This means too many props get removed in some cases.

Need to flatten intersections for the purposes of the removeExcessProperties function.

Should check if this affects other functions too.

Rtti uses `util` causing issues in Webpack 5

HI @yortus :)

We are using your other lib, http-schemas, that relies on rtti. We are using this in a browser SPA that relies on Webpack 5. Webpack 5 has stopped providing polyfils for some node based libraries like util. Is it possible to change the requirement of this library away from using util?

RR! Module not found: Error: Can't resolve 'util' in '/Users/ray/source/xxx/shared/http/node_modules/rtti/dist/commonjs'
ERR! 
ERR! BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
ERR! This is no longer the case. Verify if you need this module and configure a polyfill for it.
ERR! 
ERR! If you want to include a polyfill, you need to:
ERR! 	- add a fallback 'resolve.fallback: { "util": require.resolve("util/") }'
ERR! 	- install 'util'
ERR! If you don't want to include a polyfill, you can use an empty module like this:
ERR! 	resolve.fallback: { "util": false }
ERR! ModuleNotFoundError: Module not found: Error: Can't resolve 'util' in '/Users/xxx/shared/http/node_modules/rtti/dist/commonjs'
ERR! 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.