Comparing version 0.2.4 to 0.3.0
@@ -54,2 +54,10 @@ /** | ||
witness: A; | ||
/** | ||
* Union this Runtype with another. | ||
*/ | ||
Or<B>(B: Runtype<B>): Runtype<A | B>; | ||
/** | ||
* Intersect this Runtype with another. | ||
*/ | ||
And<B>(B: Runtype<B>): Runtype<A & B>; | ||
}; | ||
@@ -59,7 +67,7 @@ /** | ||
*/ | ||
export declare const Anything: Runtype<{}>; | ||
export declare const Always: Runtype<{} | undefined | null>; | ||
/** | ||
* Validates nothing (always fails). | ||
*/ | ||
export declare const Nothing: Runtype<never>; | ||
export declare const Never: Runtype<never>; | ||
/** | ||
@@ -115,2 +123,8 @@ * Validates that a value is undefined. | ||
/** | ||
* Construct a runtype for records of optional values. | ||
*/ | ||
export declare function Optional<O>(runtypes: { | ||
[K in keyof O]: Runtype<O[K]>; | ||
}): Runtype<Partial<O>>; | ||
/** | ||
* Construct a union runtype from runtypes for its alternatives. | ||
@@ -176,8 +190,7 @@ */ | ||
/** | ||
* Constructs a possibly-undefined Runtype. | ||
*/ | ||
export declare function Optional<A>(runtype: Runtype<A>): Runtype<A | undefined>; | ||
/** | ||
* Constructs a possibly-recursive Runtype. | ||
*/ | ||
export declare function Lazy<A>(fn: () => Runtype<A>): Runtype<A>; | ||
export declare function hasKey<K extends string>(k: K, o: {}): o is { | ||
[_ in K]: {}; | ||
}; |
@@ -10,7 +10,7 @@ "use strict"; | ||
*/ | ||
exports.Anything = runtype(function (x) { return x; }); | ||
exports.Always = runtype(function (x) { return x; }); | ||
/** | ||
* Validates nothing (always fails). | ||
*/ | ||
exports.Nothing = runtype(function (x) { | ||
exports.Never = runtype(function (x) { | ||
throw new ValidationError('Expected nothing but got something'); | ||
@@ -109,3 +109,3 @@ }); | ||
return runtype(function (x) { | ||
var xs = arr(exports.Anything).coerce(x); | ||
var xs = arr(exports.Always).coerce(x); | ||
if (strict ? xs.length !== runtypes.length : xs.length < runtypes.length) | ||
@@ -127,8 +127,27 @@ throw new ValidationError("Expected array of " + runtypes.length + " but was " + xs.length); | ||
// tslint:disable-next-line:forin | ||
for (var key in runtypes) { | ||
if (hasKey(key, x)) | ||
runtypes[key].coerce(x[key]); | ||
else | ||
throw new ValidationError("Missing property " + key); | ||
} | ||
return x; | ||
}); | ||
} | ||
exports.Record = Record; | ||
/** | ||
* Construct a runtype for records of optional values. | ||
*/ | ||
function Optional(runtypes) { | ||
return runtype(function (x) { | ||
if (x === null || x === undefined) | ||
throw new ValidationError("Expected a defined non-null value but was " + typeof x); | ||
// tslint:disable-next-line:forin | ||
for (var key in runtypes) | ||
runtypes[key].coerce(x[key]); | ||
if (hasKey(key, x)) | ||
Union(runtypes[key], exports.Undefined).coerce(x[key]); | ||
return x; | ||
}); | ||
} | ||
exports.Record = Record; | ||
exports.Optional = Optional; | ||
function Union() { | ||
@@ -164,9 +183,2 @@ var runtypes = []; | ||
/** | ||
* Constructs a possibly-undefined Runtype. | ||
*/ | ||
function Optional(runtype) { | ||
return Union(runtype, exports.Undefined); | ||
} | ||
exports.Optional = Optional; | ||
/** | ||
* Constructs a possibly-recursive Runtype. | ||
@@ -185,3 +197,4 @@ */ | ||
var witness = undefined; | ||
return { coerce: coerce, validate: validate, guard: guard, witness: witness }; | ||
var A = { coerce: coerce, validate: validate, guard: guard, witness: witness, Or: Or, And: And }; | ||
return A; | ||
function validate(value) { | ||
@@ -200,2 +213,8 @@ try { | ||
} | ||
function Or(B) { | ||
return Union(A, B); | ||
} | ||
function And(B) { | ||
return Intersect(A, B); | ||
} | ||
} | ||
@@ -209,1 +228,7 @@ var ValidationError = (function (_super) { | ||
}(Error)); | ||
// Type guard to determine if an object has a given key | ||
// If this feature gets implemented, we can use `in` instead: https://github.com/Microsoft/TypeScript/issues/10485 | ||
function hasKey(k, o) { | ||
return typeof o === 'object' && k in o; | ||
} | ||
exports.hasKey = hasKey; |
{ | ||
"name": "runtypes", | ||
"version": "0.2.4", | ||
"version": "0.3.0", | ||
"description": "Runtime type validation for (Java|Type)Script", | ||
@@ -5,0 +5,0 @@ "main": "./lib/index.js", |
@@ -5,6 +5,5 @@ # Runtypes [![Build Status](https://travis-ci.org/pelotom/runtypes.svg?branch=master)](https://travis-ci.org/pelotom/runtypes) | ||
Runtypes is a JavaScript and TypeScript library which allows you to take values about which you have no assurances and check | ||
that they conform to some type `A`. This is done by means of composable type validators of primitives, literals, arrays, | ||
tuples, records and unions. Better yet, it has TypeScript bindings which allow exactly expressing the validated results in a type-safe | ||
manner. | ||
Runtypes allow you to take values about which you have no assurances and check that they conform to some type `A`. | ||
This is done by means of composable type validators of primitives, literals, arrays, tuples, records, unions, | ||
intersections and more. | ||
@@ -19,3 +18,3 @@ ## Installation | ||
For example, suppose you have objects which represent asteroids, planets, ships and personnel. In TypeScript, you might model | ||
Suppose you have objects which represent asteroids, planets, ships and personnel. In TypeScript, you might model | ||
them like so: | ||
@@ -22,0 +21,0 @@ |
@@ -1,2 +0,20 @@ | ||
import { Runtype, Anything, Nothing, Undefined, Null, Void, Boolean, Number, String, Literal, Array, Record, Tuple, Union, Optional, Lazy, Intersect } from './index'; | ||
import { | ||
Runtype, | ||
Always, | ||
Never, | ||
Undefined, | ||
Null, | ||
Void, | ||
Boolean, | ||
Number, | ||
String, | ||
Literal, | ||
Array, | ||
Record, | ||
Optional, | ||
Tuple, | ||
Union, | ||
Intersect, | ||
Lazy, | ||
} from './index'; | ||
@@ -10,4 +28,4 @@ | ||
const runtypes = { | ||
Anything, | ||
Nothing, | ||
Always, | ||
Never, | ||
Undefined, | ||
@@ -23,3 +41,2 @@ Null, | ||
42: Literal(42), | ||
OptionalNumber: Optional(Number), | ||
String, | ||
@@ -31,5 +48,4 @@ 'hello world': Literal('hello world'), | ||
union1, | ||
optionalKey: Record({ foo: Optional(String), Boolean }), | ||
Partial: Record({ Boolean }).And(Optional({ foo: String })), | ||
Person, | ||
Intersect: Intersect(Record({ Boolean }), Record({ Number })) | ||
} | ||
@@ -44,13 +60,14 @@ | ||
const testValues: { value: {}, passes: RuntypeName[] }[] = [ | ||
{ value: undefined, passes: ['Undefined', 'Void', 'OptionalNumber'] }, | ||
{ value: undefined, passes: ['Undefined', 'Void'] }, | ||
{ value: null, passes: ['Null', 'Void'] }, | ||
{ value: true, passes: ['Boolean', 'true'] }, | ||
{ value: false, passes: ['Boolean', 'false'] }, | ||
{ value: 3, passes: ['Number', '3', 'union1', 'OptionalNumber'] }, | ||
{ value: 42, passes: ['Number', '42', 'OptionalNumber'] }, | ||
{ value: 3, passes: ['Number', '3', 'union1'] }, | ||
{ value: 42, passes: ['Number', '42'] }, | ||
{ value: 'hello world', passes: ['String', 'hello world', 'union1'] }, | ||
{ value: [true, false, true], passes: ['boolArray', 'boolTuple', 'union1'] }, | ||
{ value: { Boolean: true, Number: 3 }, passes: ['record1', 'union1', 'optionalKey', 'Intersect'] }, | ||
{ value: { Boolean: true }, passes: ['optionalKey'] }, | ||
{ value: { Boolean: true, foo: 'hello' }, passes: ['optionalKey'] }, | ||
{ value: { Boolean: true, Number: 3 }, passes: ['record1', 'union1', 'Partial'] }, | ||
{ value: { Boolean: true }, passes: ['Partial'] }, | ||
{ value: { Boolean: true, foo: undefined }, passes: ['Partial'] }, | ||
{ value: { Boolean: true, foo: 'hello' }, passes: ['Partial'] }, | ||
{ value: { name: 'Jimmy', likes: [{ name: 'Peter', likes: [] }] }, passes: ['Person'] }, | ||
@@ -64,3 +81,3 @@ ] | ||
shouldPass.Anything = true | ||
shouldPass.Always = true | ||
@@ -67,0 +84,0 @@ if (value !== undefined && value !== null) |
@@ -63,2 +63,12 @@ | ||
witness: A | ||
/** | ||
* Union this Runtype with another. | ||
*/ | ||
Or<B>(B: Runtype<B>): Runtype<A | B> | ||
/** | ||
* Intersect this Runtype with another. | ||
*/ | ||
And<B>(B: Runtype<B>): Runtype<A & B> | ||
} | ||
@@ -69,3 +79,3 @@ | ||
*/ | ||
export const Anything: Runtype<{}> = runtype(x => x) | ||
export const Always: Runtype<{} | undefined | null> = runtype(x => x) | ||
@@ -75,3 +85,3 @@ /** | ||
*/ | ||
export const Nothing: Runtype<never> = runtype(x => { | ||
export const Never: Runtype<never> = runtype(x => { | ||
throw new ValidationError('Expected nothing but got something') | ||
@@ -223,3 +233,3 @@ }) | ||
return runtype(x => { | ||
const xs = arr(Anything).coerce(x) | ||
const xs = arr(Always).coerce(x) | ||
if (strict ? xs.length !== runtypes.length : xs.length < runtypes.length) | ||
@@ -237,3 +247,3 @@ throw new ValidationError(`Expected array of ${runtypes.length} but was ${xs.length}`) | ||
export function Record<O>(runtypes: {[K in keyof O]: Runtype<O[K]> }): Runtype<O> { | ||
return runtype<O>(x => { | ||
return runtype(x => { | ||
if (x === null || x === undefined) | ||
@@ -243,4 +253,8 @@ throw new ValidationError(`Expected a defined non-null value but was ${typeof x}`) | ||
// tslint:disable-next-line:forin | ||
for (const key in runtypes) | ||
runtypes[key].coerce((x as any)[key]) | ||
for (const key in runtypes) { | ||
if (hasKey(key, x)) | ||
runtypes[key].coerce(x[key]) | ||
else | ||
throw new ValidationError(`Missing property ${key}`) | ||
} | ||
@@ -252,2 +266,19 @@ return x as O | ||
/** | ||
* Construct a runtype for records of optional values. | ||
*/ | ||
export function Optional<O>(runtypes: {[K in keyof O]: Runtype<O[K]> }): Runtype<Partial<O>> { | ||
return runtype(x => { | ||
if (x === null || x === undefined) | ||
throw new ValidationError(`Expected a defined non-null value but was ${typeof x}`) | ||
// tslint:disable-next-line:forin | ||
for (const key in runtypes) | ||
if (hasKey(key, x)) | ||
Union(runtypes[key], Undefined).coerce(x[key]) | ||
return x as Partial<O> | ||
}) | ||
} | ||
/** | ||
* Construct a union runtype from runtypes for its alternatives. | ||
@@ -1059,9 +1090,2 @@ */ | ||
/** | ||
* Constructs a possibly-undefined Runtype. | ||
*/ | ||
export function Optional<A>(runtype: Runtype<A>): Runtype<A | undefined> { | ||
return Union(runtype, Undefined) | ||
} | ||
/** | ||
* Constructs a possibly-recursive Runtype. | ||
@@ -1081,4 +1105,6 @@ */ | ||
return { coerce, validate, guard, witness } | ||
const A = { coerce, validate, guard, witness, Or, And } | ||
return A | ||
function validate(value: any): Result<A> { | ||
@@ -1096,2 +1122,10 @@ try { | ||
} | ||
function Or<B>(B: Runtype<B>): Runtype<A | B> { | ||
return Union(A, B) | ||
} | ||
function And<B>(B: Runtype<B>): Runtype<A & B> { | ||
return Intersect(A, B) | ||
} | ||
} | ||
@@ -1104,1 +1138,7 @@ | ||
} | ||
// Type guard to determine if an object has a given key | ||
// If this feature gets implemented, we can use `in` instead: https://github.com/Microsoft/TypeScript/issues/10485 | ||
export function hasKey<K extends string>(k: K, o: {}): o is { [_ in K]: {} } { | ||
return typeof o === 'object' && k in o | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
64872
1644
158