Comparing version 0.8.2 to 0.9.0-dev.20171113
@@ -15,2 +15,14 @@ # Changelog | ||
# 0.9.0 | ||
- **Breaking Change** | ||
- remove `t.map` and `t.mapWithName` (in general doesn't look serializable, needs more investigation) | ||
- remove `t.prism` (in general doesn't look serializable, needs more investigation) | ||
- change `Type` from interface to class (since TypeScript is structural shouldn't be a breaking change though) | ||
- remove `t._A` | ||
- add `Type#serialize` | ||
- add `Type#is` (in order to serialize unions and while we're at it, looks useful anyway) | ||
- remove `t.is` (now that there's `Type#is` is misleading) | ||
# 0.8.2 | ||
@@ -17,0 +29,0 @@ |
import { Either } from 'fp-ts/lib/Either'; | ||
import { Option } from 'fp-ts/lib/Option'; | ||
import { Predicate } from 'fp-ts/lib/function'; | ||
@@ -11,3 +10,3 @@ declare global { | ||
readonly key: string; | ||
readonly type: Any; | ||
readonly type: Any | NeverType; | ||
} | ||
@@ -19,177 +18,128 @@ export declare type Context = Array<ContextEntry>; | ||
} | ||
export declare type Validation<T> = Either<Array<ValidationError>, T>; | ||
export declare type Validate<T> = (value: any, context: Context) => Validation<T>; | ||
export declare type Any = Type<any>; | ||
export declare type Errors = Array<ValidationError>; | ||
export declare type Validation<A> = Either<Errors, A>; | ||
export declare type Is<A> = (v: any) => v is A; | ||
export declare type Validate<S, A> = (s: S, context: Context) => Validation<A>; | ||
export declare type Serialize<S, A> = (a: A) => S; | ||
export declare type Any = Type<any, any>; | ||
export declare type TypeOf<RT extends Any> = RT['_A']; | ||
export interface Type<A> { | ||
export declare type InputOf<RT extends Any> = RT['_S']; | ||
/** | ||
* Laws: | ||
* 1. validate(x).fold(() => x, serialize) = x | ||
* 2. validate(serialize(x)) = Right(x) | ||
*/ | ||
export declare class Type<S, A> { | ||
readonly name: string; | ||
readonly is: Is<A>; | ||
readonly validate: Validate<S, A>; | ||
readonly serialize: Serialize<S, A>; | ||
readonly _A: A; | ||
readonly name: string; | ||
readonly validate: Validate<A>; | ||
readonly _S: S; | ||
constructor(name: string, is: Is<A>, validate: Validate<S, A>, serialize: Serialize<S, A>); | ||
pipe<B>(ab: Type<A, B>, name?: string): Type<S, B>; | ||
} | ||
export declare const _A: never; | ||
export declare const identity: <A>(a: A) => A; | ||
export declare const getFunctionName: (f: any) => string; | ||
export declare const getContextEntry: (key: string, type: Type<any>) => ContextEntry; | ||
export declare const getContextEntry: (key: string, type: Type<any, any> | NeverType) => ContextEntry; | ||
export declare const getValidationError: (value: any, context: ContextEntry[]) => ValidationError; | ||
export declare const getDefaultContext: (type: Type<any, any>) => ContextEntry[]; | ||
export declare const failures: <T>(errors: ValidationError[]) => Either<ValidationError[], T>; | ||
export declare const failure: <T>(value: any, context: ContextEntry[]) => Either<ValidationError[], T>; | ||
export declare const success: <T>(value: T) => Either<ValidationError[], T>; | ||
export declare const validate: <T>(value: any, type: Type<T>) => Either<ValidationError[], T>; | ||
export declare const is: <T>(value: any, type: Type<T>) => value is T; | ||
export declare class MapType<RT extends Any, A> implements Type<A> { | ||
readonly type: RT; | ||
readonly f: (a: TypeOf<RT>) => A; | ||
readonly name: string; | ||
readonly _tag: 'MapType'; | ||
readonly _A: A; | ||
readonly validate: Validate<A>; | ||
constructor(type: RT, f: (a: TypeOf<RT>) => A, name: string); | ||
} | ||
export declare const map: <RT extends Type<any>, B>(f: (a: RT["_A"]) => B, type: RT) => MapType<RT, B>; | ||
export declare const mapWithName: <RT extends Type<any>, B>(f: (a: RT["_A"]) => B, type: RT, name: string) => MapType<RT, B>; | ||
export declare class NullType implements Type<null> { | ||
export declare const validate: <S, A>(value: S, type: Type<S, A>) => Either<ValidationError[], A>; | ||
export declare class NullType extends Type<any, null> { | ||
readonly _tag: 'NullType'; | ||
readonly _A: null; | ||
readonly name: 'null'; | ||
readonly validate: Validate<null>; | ||
constructor(); | ||
} | ||
/** An alias of `null` */ | ||
/** @alias `null` */ | ||
export declare const nullType: NullType; | ||
export declare class UndefinedType implements Type<undefined> { | ||
export declare class UndefinedType extends Type<any, undefined> { | ||
readonly _tag: 'UndefinedType'; | ||
readonly _A: undefined; | ||
readonly name: 'undefined'; | ||
readonly validate: Validate<undefined>; | ||
constructor(); | ||
} | ||
declare const undefinedType: UndefinedType; | ||
export declare class AnyType implements Type<any> { | ||
export declare class AnyType extends Type<any, any> { | ||
readonly _tag: 'AnyType'; | ||
readonly _A: any; | ||
readonly name: 'any'; | ||
readonly validate: Validate<any>; | ||
constructor(); | ||
} | ||
export declare const any: AnyType; | ||
export declare class NeverType implements Type<never> { | ||
export declare class NeverType extends Type<any, never> { | ||
readonly _tag: 'NeverType'; | ||
readonly _A: never; | ||
readonly name: 'never'; | ||
readonly validate: Validate<never>; | ||
constructor(); | ||
} | ||
export declare const never: NeverType; | ||
export declare class StringType implements Type<string> { | ||
export declare class StringType extends Type<any, string> { | ||
readonly _tag: 'StringType'; | ||
readonly _A: string; | ||
readonly name: 'string'; | ||
readonly validate: Validate<string>; | ||
constructor(); | ||
} | ||
export declare const string: StringType; | ||
export declare class NumberType implements Type<number> { | ||
export declare class NumberType extends Type<any, number> { | ||
readonly _tag: 'NumberType'; | ||
readonly _A: number; | ||
readonly name: 'number'; | ||
readonly validate: Validate<number>; | ||
constructor(); | ||
} | ||
export declare const number: NumberType; | ||
export declare class BooleanType implements Type<boolean> { | ||
export declare class BooleanType extends Type<any, boolean> { | ||
readonly _tag: 'BooleanType'; | ||
readonly _A: boolean; | ||
readonly name: 'boolean'; | ||
readonly validate: Validate<boolean>; | ||
constructor(); | ||
} | ||
export declare const boolean: BooleanType; | ||
export declare class AnyArrayType implements Type<Array<any>> { | ||
export declare class AnyArrayType extends Type<any, Array<any>> { | ||
readonly _tag: 'AnyArrayType'; | ||
readonly _A: Array<any>; | ||
readonly name: 'Array'; | ||
readonly validate: Validate<Array<any>>; | ||
constructor(); | ||
} | ||
declare const arrayType: AnyArrayType; | ||
export declare class AnyDictionaryType implements Type<{ | ||
export declare class AnyDictionaryType extends Type<any, { | ||
[key: string]: any; | ||
}> { | ||
readonly _tag: 'AnyDictionaryType'; | ||
readonly _A: { | ||
[key: string]: any; | ||
}; | ||
readonly name: 'Dictionary'; | ||
readonly validate: Validate<{ | ||
[key: string]: any; | ||
}>; | ||
constructor(); | ||
} | ||
export declare const Dictionary: AnyDictionaryType; | ||
export declare class ObjectType implements Type<object> { | ||
export declare class ObjectType extends Type<any, object> { | ||
readonly _tag: 'ObjectType'; | ||
readonly _A: object; | ||
readonly name: 'object'; | ||
readonly validate: Validate<object>; | ||
constructor(); | ||
} | ||
export declare const object: ObjectType; | ||
export declare class FunctionType implements Type<Function> { | ||
export declare class FunctionType extends Type<any, Function> { | ||
readonly _tag: 'FunctionType'; | ||
readonly _A: Function; | ||
readonly name: 'Function'; | ||
readonly validate: Validate<Function>; | ||
constructor(); | ||
} | ||
declare const functionType: FunctionType; | ||
export declare class RefinementType<RT extends Any> implements Type<TypeOf<RT>> { | ||
export declare class RefinementType<RT extends Any> extends Type<InputOf<RT>, TypeOf<RT>> { | ||
readonly type: RT; | ||
readonly predicate: Predicate<TypeOf<RT>>; | ||
readonly name: string; | ||
readonly _tag: 'RefinementType'; | ||
readonly _A: TypeOf<RT>; | ||
readonly validate: Validate<TypeOf<RT>>; | ||
constructor(type: RT, predicate: Predicate<TypeOf<RT>>, name?: string); | ||
constructor(name: string, type: RT, predicate: Predicate<TypeOf<RT>>); | ||
} | ||
export declare const refinement: <RT extends Type<any>>(type: RT, predicate: Predicate<RT["_A"]>, name?: string | undefined) => RefinementType<RT>; | ||
export declare const refinement: <RT extends Type<any, any>>(type: RT, predicate: Predicate<RT["_A"]>, name?: string) => RefinementType<RT>; | ||
export declare const Integer: RefinementType<NumberType>; | ||
export declare type GetOption<S, A> = (s: S) => Option<A>; | ||
export declare class PrismType<RT extends Any, A> implements Type<A> { | ||
readonly type: RT; | ||
readonly getOption: GetOption<TypeOf<RT>, A>; | ||
readonly name: string; | ||
readonly _tag: 'PrismType'; | ||
readonly _A: A; | ||
readonly validate: Validate<A>; | ||
constructor(type: RT, getOption: GetOption<TypeOf<RT>, A>, name?: string); | ||
} | ||
export declare const prism: <RT extends Type<any>, A>(type: RT, getOption: GetOption<RT["_A"], A>, name?: string | undefined) => PrismType<RT, A>; | ||
export declare class LiteralType<V extends string | number | boolean> implements Type<V> { | ||
export declare class LiteralType<V extends string | number | boolean> extends Type<any, V> { | ||
readonly value: V; | ||
readonly name: string; | ||
readonly _tag: 'LiteralType'; | ||
readonly _A: V; | ||
readonly validate: Validate<V>; | ||
constructor(value: V, name?: string); | ||
constructor(name: string, value: V); | ||
} | ||
export declare const literal: <V extends string | number | boolean>(value: V, name?: string | undefined) => LiteralType<V>; | ||
export declare const literal: <V extends string | number | boolean>(value: V, name?: string) => LiteralType<V>; | ||
export declare class KeyofType<D extends { | ||
[key: string]: any; | ||
}> implements Type<keyof D> { | ||
}> extends Type<any, keyof D> { | ||
readonly keys: D; | ||
readonly name: string; | ||
readonly _tag: 'KeyofType'; | ||
readonly _A: keyof D; | ||
readonly validate: Validate<keyof D>; | ||
constructor(keys: D, name?: string); | ||
constructor(name: string, keys: D); | ||
} | ||
export declare const keyof: <D extends { | ||
[key: string]: any; | ||
}>(keys: D, name?: string | undefined) => KeyofType<D>; | ||
export declare class RecursiveType<T> implements Type<T> { | ||
readonly name: string; | ||
readonly validate: Validate<T>; | ||
}>(keys: D, name?: string) => KeyofType<D>; | ||
export declare class RecursiveType<T> extends Type<any, T> { | ||
readonly _tag: 'RecursiveType'; | ||
readonly _A: T; | ||
readonly type: Any; | ||
constructor(name: string, validate: Validate<T>); | ||
constructor(name: string, is: Is<T>, validate: Validate<any, T>, serialize: Serialize<any, T>); | ||
} | ||
export declare const recursion: <T>(name: string, definition: (self: Type<any>) => Type<any>) => RecursiveType<T>; | ||
export declare class ArrayType<RT extends Any> implements Type<Array<TypeOf<RT>>> { | ||
export declare const recursion: <T>(name: string, definition: (self: Type<any, any>) => Type<any, any>) => RecursiveType<T>; | ||
export declare class ArrayType<RT extends Any> extends Type<any, Array<TypeOf<RT>>> { | ||
readonly type: RT; | ||
readonly name: string; | ||
readonly _tag: 'ArrayType'; | ||
readonly _A: Array<TypeOf<RT>>; | ||
readonly validate: Validate<Array<TypeOf<RT>>>; | ||
constructor(type: RT, name?: string); | ||
constructor(name: string, is: ArrayType<RT>['is'], validate: ArrayType<RT>['validate'], serialize: ArrayType<RT>['serialize'], type: RT); | ||
} | ||
export declare const array: <RT extends Type<any>>(type: RT, name?: string | undefined) => ArrayType<RT>; | ||
export declare const array: <RT extends Type<any, any>>(type: RT, name?: string) => ArrayType<RT>; | ||
export declare type Props = { | ||
@@ -201,12 +151,9 @@ [key: string]: Any; | ||
}; | ||
export declare class InterfaceType<P extends Props> implements Type<InterfaceOf<P>> { | ||
export declare class InterfaceType<P extends Props> extends Type<any, InterfaceOf<P>> { | ||
readonly props: P; | ||
readonly name: string; | ||
readonly _tag: 'InterfaceType'; | ||
readonly _A: InterfaceOf<P>; | ||
readonly validate: Validate<InterfaceOf<P>>; | ||
constructor(props: P, name?: string); | ||
constructor(name: string, is: InterfaceType<P>['is'], validate: InterfaceType<P>['validate'], serialize: InterfaceType<P>['serialize'], props: P); | ||
} | ||
/** An alias of `interface` */ | ||
export declare const type: <P extends Props>(props: P, name?: string | undefined) => InterfaceType<P>; | ||
/** @alias `interface` */ | ||
export declare const type: <P extends Props>(props: P, name?: string) => InterfaceType<P>; | ||
export declare type PartialOf<P extends Props> = { | ||
@@ -216,45 +163,28 @@ [K in keyof P]?: TypeOf<P[K]>; | ||
export declare type PartialPropsOf<P extends Props> = { | ||
[K in keyof P]: UnionType<[P[K], Type<undefined>], [TypeOf<P[K]>, undefined]>; | ||
[K in keyof P]: UnionType<[P[K], UndefinedType]>; | ||
}; | ||
export declare class PartialType<P extends Props> implements Type<PartialOf<P>> { | ||
export declare class PartialType<P extends Props> extends Type<any, PartialOf<P>> { | ||
readonly props: P; | ||
readonly _tag: 'PartialType'; | ||
readonly _A: PartialOf<P>; | ||
readonly validate: Validate<PartialOf<P>>; | ||
readonly name: string; | ||
constructor(props: P, name?: string); | ||
constructor(name: string, is: PartialType<P>['is'], validate: PartialType<P>['validate'], serialize: PartialType<P>['serialize'], props: P); | ||
} | ||
export declare const partial: <P extends Props>(props: P, name?: string | undefined) => PartialType<P>; | ||
export declare class DictionaryType<D extends Type<string>, C extends Any> implements Type<{ | ||
export declare const partial: <P extends Props>(props: P, name?: string) => PartialType<P>; | ||
export declare class DictionaryType<D extends Any, C extends Any> extends Type<any, { | ||
[K in TypeOf<D>]: TypeOf<C>; | ||
}> { | ||
readonly domain: D; | ||
readonly codomain: C; | ||
readonly name: string; | ||
readonly _tag: 'DictionaryType'; | ||
readonly _A: { | ||
[K in TypeOf<D>]: TypeOf<C>; | ||
}; | ||
readonly validate: Validate<{ | ||
[K in TypeOf<D>]: TypeOf<C>; | ||
}>; | ||
constructor(domain: D, codomain: C, name?: string); | ||
constructor(name: string, is: DictionaryType<D, C>['is'], validate: DictionaryType<D, C>['validate'], serialize: DictionaryType<D, C>['serialize'], codomain: C); | ||
} | ||
export declare const dictionary: <D extends Type<string>, C extends Type<any>>(domain: D, codomain: C, name?: string | undefined) => DictionaryType<D, C>; | ||
export declare class UnionType<RTS extends [Any], U = TypeOf<RTS['_A']>> implements Type<U> { | ||
export declare const dictionary: <D extends Type<any, any>, C extends Type<any, any>>(domain: D, codomain: C, name?: string) => DictionaryType<D, C>; | ||
export declare class UnionType<RTS extends Array<Any>> extends Type<any, TypeOf<RTS['_A']>> { | ||
readonly types: RTS; | ||
readonly name: string; | ||
readonly _tag: 'UnionType'; | ||
readonly _A: U; | ||
readonly validate: Validate<U>; | ||
constructor(types: RTS, name?: string); | ||
constructor(name: string, is: UnionType<RTS>['is'], validate: UnionType<RTS>['validate'], serialize: UnionType<RTS>['serialize'], types: RTS); | ||
} | ||
export declare const union: <RTS extends [Type<any>]>(types: RTS, name?: string | undefined) => UnionType<RTS, RTS["_A"]["_A"]>; | ||
export declare class IntersectionType<RTS extends Array<Any>, I> implements Type<I> { | ||
export declare const union: <RTS extends Type<any, any>[]>(types: RTS, name?: string) => UnionType<RTS>; | ||
export declare class IntersectionType<RTS extends Array<Any>, A> extends Type<any, A> { | ||
readonly types: RTS; | ||
readonly name: string; | ||
readonly _tag: 'IntersectionType'; | ||
readonly _A: I; | ||
readonly validate: Validate<I>; | ||
constructor(types: RTS, name?: string); | ||
constructor(name: string, is: Is<A>, validate: Validate<any, A>, serialize: Serialize<any, A>, types: RTS); | ||
} | ||
@@ -266,9 +196,6 @@ export declare function intersection<A extends Any, B extends Any, C extends Any, D extends Any, E extends Any>(types: [A, B, C, D, E], name?: string): IntersectionType<[A, B, C, D, E], TypeOf<A> & TypeOf<B> & TypeOf<C> & TypeOf<D> & TypeOf<E>>; | ||
export declare function intersection<A extends Any>(types: [A], name?: string): IntersectionType<[A], TypeOf<A>>; | ||
export declare class TupleType<RTS extends Array<Any>, I> implements Type<I> { | ||
export declare class TupleType<RTS extends Array<Any>, A> extends Type<any, A> { | ||
readonly types: RTS; | ||
readonly name: string; | ||
readonly _tag: 'TupleType'; | ||
readonly _A: I; | ||
readonly validate: Validate<I>; | ||
constructor(types: RTS, name?: string); | ||
constructor(name: string, is: Is<A>, validate: Validate<any, A>, serialize: Serialize<any, A>, types: RTS); | ||
} | ||
@@ -280,27 +207,18 @@ export declare function tuple<A extends Any, B extends Any, C extends Any, D extends Any, E extends Any>(types: [A, B, C, D, E], name?: string): TupleType<[A, B, C, D, E], [TypeOf<A>, TypeOf<B>, TypeOf<C>, TypeOf<D>, TypeOf<E>]>; | ||
export declare function tuple<A extends Any>(types: [A], name?: string): TupleType<[A], [TypeOf<A>]>; | ||
export declare class ReadonlyType<RT extends Any> implements Type<Readonly<TypeOf<RT>>> { | ||
export declare class ReadonlyType<RT extends Any> extends Type<any, Readonly<TypeOf<RT>>> { | ||
readonly type: RT; | ||
readonly name: string; | ||
readonly _tag: 'ReadonlyType'; | ||
readonly _A: Readonly<TypeOf<RT>>; | ||
readonly validate: Validate<Readonly<TypeOf<RT>>>; | ||
constructor(type: RT, name?: string); | ||
constructor(name: string, is: ReadonlyType<RT>['is'], validate: ReadonlyType<RT>['validate'], serialize: ReadonlyType<RT>['serialize'], type: RT); | ||
} | ||
export declare const readonly: <RT extends Type<any>>(type: RT, name?: string | undefined) => ReadonlyType<RT>; | ||
export declare class ReadonlyArrayType<RT extends Any> implements Type<ReadonlyArray<TypeOf<RT>>> { | ||
export declare const readonly: <RT extends Type<any, any>>(type: RT, name?: string) => ReadonlyType<RT>; | ||
export declare class ReadonlyArrayType<RT extends Any> extends Type<any, ReadonlyArray<TypeOf<RT>>> { | ||
readonly type: RT; | ||
readonly name: string; | ||
readonly _tag: 'ReadonlyArrayType'; | ||
readonly _A: ReadonlyArray<TypeOf<RT>>; | ||
readonly validate: Validate<ReadonlyArray<TypeOf<RT>>>; | ||
constructor(type: RT, name?: string); | ||
constructor(name: string, is: ReadonlyArrayType<RT>['is'], validate: ReadonlyArrayType<RT>['validate'], serialize: ReadonlyArrayType<RT>['serialize'], type: RT); | ||
} | ||
export declare const readonlyArray: <RT extends Type<any>>(type: RT, name?: string | undefined) => ReadonlyArrayType<RT>; | ||
export declare class StrictType<P extends Props> implements Type<InterfaceOf<P>> { | ||
export declare const readonlyArray: <RT extends Type<any, any>>(type: RT, name?: string) => ReadonlyArrayType<RT>; | ||
export declare class StrictType<P extends Props> extends Type<any, InterfaceOf<P>> { | ||
readonly props: P; | ||
readonly _tag: 'StrictType'; | ||
readonly _A: InterfaceOf<P>; | ||
readonly validate: Validate<InterfaceOf<P>>; | ||
readonly name: string; | ||
constructor(props: P, name?: string); | ||
constructor(name: string, is: StrictType<P>['is'], validate: StrictType<P>['validate'], serialize: StrictType<P>['serialize'], props: P); | ||
} | ||
@@ -307,0 +225,0 @@ /** Specifies that only the given interface properties are allowed */ |
837
lib/index.js
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
@@ -12,7 +22,26 @@ for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
var Either_1 = require("fp-ts/lib/Either"); | ||
exports._A = undefined; | ||
/** | ||
* Laws: | ||
* 1. validate(x).fold(() => x, serialize) = x | ||
* 2. validate(serialize(x)) = Right(x) | ||
*/ | ||
var Type = /** @class */ (function () { | ||
function Type(name, is, validate, serialize) { | ||
this.name = name; | ||
this.is = is; | ||
this.validate = validate; | ||
this.serialize = serialize; | ||
} | ||
Type.prototype.pipe = function (ab, name) { | ||
var _this = this; | ||
return new Type(name || "pipe(" + this.name + ", " + ab.name + ")", function (v) { return _this.is(v) && ab.is(v); }, function (s, c) { return _this.validate(s, c).chain(function (a) { return ab.validate(a, c); }); }, this.serialize === exports.identity && ab.serialize === exports.identity ? exports.identity : function (b) { return _this.serialize(ab.serialize(b)); }); | ||
}; | ||
return Type; | ||
}()); | ||
exports.Type = Type; | ||
exports.identity = function (a) { return a; }; | ||
exports.getFunctionName = function (f) { return f.displayName || f.name || "<function" + f.length + ">"; }; | ||
exports.getContextEntry = function (key, type) { return ({ key: key, type: type }); }; | ||
exports.getValidationError = function (value, context) { return ({ value: value, context: context }); }; | ||
var pushAll = function (xs, ys) { return Array.prototype.push.apply(xs, ys); }; | ||
exports.getDefaultContext = function (type) { return [{ key: '', type: type }]; }; | ||
exports.failures = function (errors) { return new Either_1.Left(errors); }; | ||
@@ -23,139 +52,134 @@ exports.failure = function (value, context) { | ||
exports.success = function (value) { return new Either_1.Right(value); }; | ||
var getDefaultContext = function (type) { return [{ key: '', type: type }]; }; | ||
exports.validate = function (value, type) { return type.validate(value, getDefaultContext(type)); }; | ||
exports.is = function (value, type) { return Either_1.isRight(exports.validate(value, type)); }; | ||
var MapType = /** @class */ (function () { | ||
function MapType(type, f, name) { | ||
this.type = type; | ||
this.f = f; | ||
this.name = name; | ||
this._tag = 'MapType'; | ||
this.validate = function (v, c) { return type.validate(v, c).map(f); }; | ||
} | ||
return MapType; | ||
}()); | ||
exports.MapType = MapType; | ||
exports.map = function (f, type) { | ||
return exports.mapWithName(f, type, "(" + type.name + " => ?)"); | ||
exports.validate = function (value, type) { | ||
return type.validate(value, exports.getDefaultContext(type)); | ||
}; | ||
exports.mapWithName = function (f, type, name) { | ||
return new MapType(type, f, name); | ||
}; | ||
var pushAll = function (xs, ys) { return Array.prototype.push.apply(xs, ys); }; | ||
// | ||
// basic types | ||
// | ||
var NullType = /** @class */ (function () { | ||
var NullType = /** @class */ (function (_super) { | ||
__extends(NullType, _super); | ||
function NullType() { | ||
this._tag = 'NullType'; | ||
this.name = 'null'; | ||
this.validate = function (v, c) { return (v === null ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'null', function (v) { return v === null; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'NullType'; | ||
return _this; | ||
} | ||
return NullType; | ||
}()); | ||
}(Type)); | ||
exports.NullType = NullType; | ||
/** An alias of `null` */ | ||
/** @alias `null` */ | ||
exports.nullType = new NullType(); | ||
exports.null = exports.nullType; | ||
var UndefinedType = /** @class */ (function () { | ||
var UndefinedType = /** @class */ (function (_super) { | ||
__extends(UndefinedType, _super); | ||
function UndefinedType() { | ||
this._tag = 'UndefinedType'; | ||
this.name = 'undefined'; | ||
this.validate = function (v, c) { return (v === void 0 ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'undefined', function (v) { return v === void 0; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'UndefinedType'; | ||
return _this; | ||
} | ||
return UndefinedType; | ||
}()); | ||
}(Type)); | ||
exports.UndefinedType = UndefinedType; | ||
var undefinedType = new UndefinedType(); | ||
exports.undefined = undefinedType; | ||
var AnyType = /** @class */ (function () { | ||
var AnyType = /** @class */ (function (_super) { | ||
__extends(AnyType, _super); | ||
function AnyType() { | ||
this._tag = 'AnyType'; | ||
this.name = 'any'; | ||
this.validate = function (v, _) { return exports.success(v); }; | ||
var _this = _super.call(this, 'any', function (_) { return true; }, exports.success, exports.identity) || this; | ||
_this._tag = 'AnyType'; | ||
return _this; | ||
} | ||
return AnyType; | ||
}()); | ||
}(Type)); | ||
exports.AnyType = AnyType; | ||
exports.any = new AnyType(); | ||
var NeverType = /** @class */ (function () { | ||
var NeverType = /** @class */ (function (_super) { | ||
__extends(NeverType, _super); | ||
function NeverType() { | ||
this._tag = 'NeverType'; | ||
this.name = 'never'; | ||
this.validate = function (v, c) { return exports.failure(v, c); }; | ||
var _this = _super.call(this, 'never', function (_) { return false; }, function (s, c) { return exports.failure(s, c); }, function () { | ||
throw new Error('cannot serialize never'); | ||
}) || this; | ||
_this._tag = 'NeverType'; | ||
return _this; | ||
} | ||
return NeverType; | ||
}()); | ||
}(Type)); | ||
exports.NeverType = NeverType; | ||
exports.never = new NeverType(); | ||
var StringType = /** @class */ (function () { | ||
var StringType = /** @class */ (function (_super) { | ||
__extends(StringType, _super); | ||
function StringType() { | ||
this._tag = 'StringType'; | ||
this.name = 'string'; | ||
this.validate = function (v, c) { return (typeof v === 'string' ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'string', function (v) { return typeof v === 'string'; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'StringType'; | ||
return _this; | ||
} | ||
return StringType; | ||
}()); | ||
}(Type)); | ||
exports.StringType = StringType; | ||
exports.string = new StringType(); | ||
var NumberType = /** @class */ (function () { | ||
var NumberType = /** @class */ (function (_super) { | ||
__extends(NumberType, _super); | ||
function NumberType() { | ||
this._tag = 'NumberType'; | ||
this.name = 'number'; | ||
this.validate = function (v, c) { return (typeof v === 'number' ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'number', function (v) { return typeof v === 'number'; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'NumberType'; | ||
return _this; | ||
} | ||
return NumberType; | ||
}()); | ||
}(Type)); | ||
exports.NumberType = NumberType; | ||
exports.number = new NumberType(); | ||
var BooleanType = /** @class */ (function () { | ||
var BooleanType = /** @class */ (function (_super) { | ||
__extends(BooleanType, _super); | ||
function BooleanType() { | ||
this._tag = 'BooleanType'; | ||
this.name = 'boolean'; | ||
this.validate = function (v, c) { return (typeof v === 'boolean' ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'boolean', function (v) { return typeof v === 'boolean'; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'BooleanType'; | ||
return _this; | ||
} | ||
return BooleanType; | ||
}()); | ||
}(Type)); | ||
exports.BooleanType = BooleanType; | ||
exports.boolean = new BooleanType(); | ||
var AnyArrayType = /** @class */ (function () { | ||
var AnyArrayType = /** @class */ (function (_super) { | ||
__extends(AnyArrayType, _super); | ||
function AnyArrayType() { | ||
this._tag = 'AnyArrayType'; | ||
this.name = 'Array'; | ||
this.validate = function (v, c) { return (Array.isArray(v) ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'Array', function (v) { return Array.isArray(v); }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'AnyArrayType'; | ||
return _this; | ||
} | ||
return AnyArrayType; | ||
}()); | ||
}(Type)); | ||
exports.AnyArrayType = AnyArrayType; | ||
var arrayType = new AnyArrayType(); | ||
exports.Array = arrayType; | ||
var AnyDictionaryType = /** @class */ (function () { | ||
var AnyDictionaryType = /** @class */ (function (_super) { | ||
__extends(AnyDictionaryType, _super); | ||
function AnyDictionaryType() { | ||
this._tag = 'AnyDictionaryType'; | ||
this.name = 'Dictionary'; | ||
this.validate = function (v, c) { | ||
return v !== null && typeof v === 'object' ? exports.success(v) : exports.failure(v, c); | ||
}; | ||
var _this = _super.call(this, 'Dictionary', function (v) { return v !== null && typeof v === 'object'; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'AnyDictionaryType'; | ||
return _this; | ||
} | ||
return AnyDictionaryType; | ||
}()); | ||
}(Type)); | ||
exports.AnyDictionaryType = AnyDictionaryType; | ||
exports.Dictionary = new AnyDictionaryType(); | ||
var ObjectType = /** @class */ (function () { | ||
var ObjectType = /** @class */ (function (_super) { | ||
__extends(ObjectType, _super); | ||
function ObjectType() { | ||
this._tag = 'ObjectType'; | ||
this.name = 'object'; | ||
this.validate = exports.Dictionary.validate; | ||
var _this = _super.call(this, 'object', exports.Dictionary.is, exports.Dictionary.validate, exports.identity) || this; | ||
_this._tag = 'ObjectType'; | ||
return _this; | ||
} | ||
return ObjectType; | ||
}()); | ||
}(Type)); | ||
exports.ObjectType = ObjectType; | ||
exports.object = new ObjectType(); | ||
var FunctionType = /** @class */ (function () { | ||
var FunctionType = /** @class */ (function (_super) { | ||
__extends(FunctionType, _super); | ||
function FunctionType() { | ||
this._tag = 'FunctionType'; | ||
this.name = 'Function'; | ||
this.validate = function (v, c) { return (typeof v === 'function' ? exports.success(v) : exports.failure(v, c)); }; | ||
var _this = _super.call(this, 'Function', function (v) { return typeof v === 'function'; }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this._tag = 'FunctionType'; | ||
return _this; | ||
} | ||
return FunctionType; | ||
}()); | ||
}(Type)); | ||
exports.FunctionType = FunctionType; | ||
@@ -167,62 +191,54 @@ var functionType = new FunctionType(); | ||
// | ||
var RefinementType = /** @class */ (function () { | ||
function RefinementType(type, predicate, name) { | ||
if (name === void 0) { name = "(" + type.name + " | " + exports.getFunctionName(predicate) + ")"; } | ||
this.type = type; | ||
this.predicate = predicate; | ||
this.name = name; | ||
this._tag = 'RefinementType'; | ||
this.validate = function (v, c) { return type.validate(v, c).chain(function (t) { return (predicate(t) ? exports.success(t) : exports.failure(v, c)); }); }; | ||
var RefinementType = /** @class */ (function (_super) { | ||
__extends(RefinementType, _super); | ||
function RefinementType(name, type, predicate) { | ||
var _this = _super.call(this, name, function (v) { return type.is(v) && predicate(v); }, function (s, c) { return type.validate(s, c).chain(function (a) { return (predicate(a) ? exports.success(a) : exports.failure(a, c)); }); }, type.serialize) || this; | ||
_this.type = type; | ||
_this.predicate = predicate; | ||
_this._tag = 'RefinementType'; | ||
return _this; | ||
} | ||
return RefinementType; | ||
}()); | ||
}(Type)); | ||
exports.RefinementType = RefinementType; | ||
exports.refinement = function (type, predicate, name) { return new RefinementType(type, predicate, name); }; | ||
exports.refinement = function (type, predicate, name) { | ||
if (name === void 0) { name = "(" + type.name + " | " + exports.getFunctionName(predicate) + ")"; } | ||
return new RefinementType(name, type, predicate); | ||
}; | ||
exports.Integer = exports.refinement(exports.number, function (n) { return n % 1 === 0; }, 'Integer'); | ||
var PrismType = /** @class */ (function () { | ||
function PrismType(type, getOption, name) { | ||
if (name === void 0) { name = "Prism<" + type.name + ", ?>"; } | ||
this.type = type; | ||
this.getOption = getOption; | ||
this.name = name; | ||
this._tag = 'PrismType'; | ||
this.validate = function (v, c) { return type.validate(v, c).chain(function (a) { return getOption(a).fold(function () { return exports.failure(a, c); }, function (b) { return exports.success(b); }); }); }; | ||
} | ||
return PrismType; | ||
}()); | ||
exports.PrismType = PrismType; | ||
exports.prism = function (type, getOption, name) { return new PrismType(type, getOption, name); }; | ||
// | ||
// literal types | ||
// literals | ||
// | ||
var LiteralType = /** @class */ (function () { | ||
function LiteralType(value, name) { | ||
if (name === void 0) { name = JSON.stringify(value); } | ||
this.value = value; | ||
this.name = name; | ||
this._tag = 'LiteralType'; | ||
this.validate = function (v, c) { return (v === value ? exports.success(value) : exports.failure(v, c)); }; | ||
var LiteralType = /** @class */ (function (_super) { | ||
__extends(LiteralType, _super); | ||
function LiteralType(name, value) { | ||
var _this = _super.call(this, name, function (v) { return v === value; }, function (s, c) { return (_this.is(s) ? exports.success(value) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this.value = value; | ||
_this._tag = 'LiteralType'; | ||
return _this; | ||
} | ||
return LiteralType; | ||
}()); | ||
}(Type)); | ||
exports.LiteralType = LiteralType; | ||
exports.literal = function (value, name) { | ||
return new LiteralType(value, name); | ||
if (name === void 0) { name = JSON.stringify(value); } | ||
return new LiteralType(name, value); | ||
}; | ||
// | ||
// keyof types | ||
// keyof | ||
// | ||
var KeyofType = /** @class */ (function () { | ||
function KeyofType(keys, name) { | ||
if (name === void 0) { name = "(keyof " + JSON.stringify(Object.keys(keys)) + ")"; } | ||
this.keys = keys; | ||
this.name = name; | ||
this._tag = 'KeyofType'; | ||
this.validate = function (v, c) { return (keys.hasOwnProperty(v) ? exports.success(v) : exports.failure(v, c)); }; | ||
var KeyofType = /** @class */ (function (_super) { | ||
__extends(KeyofType, _super); | ||
function KeyofType(name, keys) { | ||
var _this = _super.call(this, name, function (v) { return exports.string.is(v) && keys.hasOwnProperty(v); }, function (s, c) { return (_this.is(s) ? exports.success(s) : exports.failure(s, c)); }, exports.identity) || this; | ||
_this.keys = keys; | ||
_this._tag = 'KeyofType'; | ||
return _this; | ||
} | ||
return KeyofType; | ||
}()); | ||
}(Type)); | ||
exports.KeyofType = KeyofType; | ||
exports.keyof = function (keys, name) { | ||
return new KeyofType(keys, name); | ||
if (name === void 0) { name = "(keyof " + JSON.stringify(Object.keys(keys)) + ")"; } | ||
return new KeyofType(name, keys); | ||
}; | ||
@@ -232,15 +248,17 @@ // | ||
// | ||
var RecursiveType = /** @class */ (function () { | ||
function RecursiveType(name, validate) { | ||
this.name = name; | ||
this.validate = validate; | ||
this._tag = 'RecursiveType'; | ||
var RecursiveType = /** @class */ (function (_super) { | ||
__extends(RecursiveType, _super); | ||
function RecursiveType(name, is, validate, serialize) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this._tag = 'RecursiveType'; | ||
return _this; | ||
} | ||
return RecursiveType; | ||
}()); | ||
}(Type)); | ||
exports.RecursiveType = RecursiveType; | ||
exports.recursion = function (name, definition) { | ||
var Self = new RecursiveType(name, function (v, c) { return type.validate(v, c); }); | ||
var Self = new RecursiveType(name, function (v) { return type.is(v); }, function (s, c) { return type.validate(s, c); }, exports.identity); | ||
var type = definition(Self); | ||
Self.type = type; | ||
Self.serialize = type.serialize; | ||
return Self; | ||
@@ -251,172 +269,262 @@ }; | ||
// | ||
var ArrayType = /** @class */ (function () { | ||
function ArrayType(type, name) { | ||
if (name === void 0) { name = "Array<" + type.name + ">"; } | ||
this.type = type; | ||
this.name = name; | ||
this._tag = 'ArrayType'; | ||
this.validate = function (v, c) { | ||
return arrayType.validate(v, c).chain(function (as) { | ||
var t = []; | ||
var errors = []; | ||
var changed = false; | ||
var _loop_1 = function (i) { | ||
var a = as[i]; | ||
var validation = type.validate(a, c.concat(exports.getContextEntry(String(i), type))); | ||
validation.fold(function (error) { return pushAll(errors, error); }, function (va) { | ||
changed = changed || va !== a; | ||
t.push(va); | ||
}); | ||
}; | ||
for (var i = 0; i < as.length; i++) { | ||
_loop_1(i); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success(changed ? t : as); | ||
}); | ||
}; | ||
var ArrayType = /** @class */ (function (_super) { | ||
__extends(ArrayType, _super); | ||
function ArrayType(name, is, validate, serialize, type) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.type = type; | ||
_this._tag = 'ArrayType'; | ||
return _this; | ||
} | ||
return ArrayType; | ||
}()); | ||
}(Type)); | ||
exports.ArrayType = ArrayType; | ||
exports.array = function (type, name) { return new ArrayType(type, name); }; | ||
var InterfaceType = /** @class */ (function () { | ||
function InterfaceType(props, name) { | ||
if (name === void 0) { name = "{ " + Object.keys(props).map(function (k) { return k + ": " + props[k].name; }).join(', ') + " }"; } | ||
this.props = props; | ||
this.name = name; | ||
this._tag = 'InterfaceType'; | ||
this.validate = function (v, c) { | ||
return exports.Dictionary.validate(v, c).chain(function (o) { | ||
var t = __assign({}, o); | ||
var errors = []; | ||
var changed = false; | ||
var _loop_2 = function (k) { | ||
var ok = o[k]; | ||
var type_1 = props[k]; | ||
var validation = type_1.validate(ok, c.concat(exports.getContextEntry(k, type_1))); | ||
validation.fold(function (error) { return pushAll(errors, error); }, function (vok) { | ||
changed = changed || vok !== ok; | ||
t[k] = vok; | ||
}); | ||
}; | ||
for (var k in props) { | ||
_loop_2(k); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success((changed ? t : o)); | ||
}); | ||
}; | ||
exports.array = function (type, name) { | ||
if (name === void 0) { name = "Array<" + type.name + ">"; } | ||
return new ArrayType(name, function (v) { return arrayType.is(v) && v.every(type.is); }, function (s, c) { | ||
return arrayType.validate(s, c).chain(function (xs) { | ||
var a = []; | ||
var errors = []; | ||
var changed = false; | ||
var _loop_1 = function (i) { | ||
var x = xs[i]; | ||
var validation = type.validate(x, c.concat(exports.getContextEntry(String(i), type))); | ||
validation.fold(function (e) { return pushAll(errors, e); }, function (vx) { | ||
changed = changed || vx !== x; | ||
a.push(vx); | ||
}); | ||
}; | ||
for (var i = 0; i < xs.length; i++) { | ||
_loop_1(i); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success(changed ? a : xs); | ||
}); | ||
}, type.serialize === exports.identity ? exports.identity : function (a) { return a.map(type.serialize); }, type); | ||
}; | ||
var InterfaceType = /** @class */ (function (_super) { | ||
__extends(InterfaceType, _super); | ||
function InterfaceType(name, is, validate, serialize, props) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.props = props; | ||
_this._tag = 'InterfaceType'; | ||
return _this; | ||
} | ||
return InterfaceType; | ||
}()); | ||
}(Type)); | ||
exports.InterfaceType = InterfaceType; | ||
/** An alias of `interface` */ | ||
exports.type = function (props, name) { return new InterfaceType(props, name); }; | ||
exports.interface = exports.type; | ||
var PartialType = /** @class */ (function () { | ||
function PartialType(props, name) { | ||
this.props = props; | ||
this._tag = 'PartialType'; | ||
var partials = {}; | ||
var getNameFromProps = function (props) { | ||
return "{ " + Object.keys(props).map(function (k) { return k + ": " + props[k].name; }).join(', ') + " }"; | ||
}; | ||
var useIdentity = function (props) { | ||
for (var k in props) { | ||
if (props[k].serialize !== exports.identity) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}; | ||
/** @alias `interface` */ | ||
exports.type = function (props, name) { | ||
if (name === void 0) { name = getNameFromProps(props); } | ||
return new InterfaceType(name, function (v) { | ||
if (!exports.Dictionary.is(v)) { | ||
return false; | ||
} | ||
for (var k in props) { | ||
partials[k] = exports.union([props[k], undefinedType]); | ||
if (!props[k].is(v[k])) { | ||
return false; | ||
} | ||
} | ||
var partial = exports.type(partials); | ||
this.name = name || partial.name; | ||
this.validate = function (v, c) { return partial.validate(v, c); }; | ||
return true; | ||
}, function (s, c) { | ||
return exports.Dictionary.validate(s, c).chain(function (o) { | ||
var a = __assign({}, o); | ||
var errors = []; | ||
var changed = false; | ||
var _loop_2 = function (k) { | ||
var ok = o[k]; | ||
var type_1 = props[k]; | ||
var validation = type_1.validate(ok, c.concat(exports.getContextEntry(k, type_1))); | ||
validation.fold(function (e) { return pushAll(errors, e); }, function (vok) { | ||
changed = changed || vok !== ok; | ||
a[k] = vok; | ||
}); | ||
}; | ||
for (var k in props) { | ||
_loop_2(k); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success((changed ? a : o)); | ||
}); | ||
}, useIdentity(props) | ||
? exports.identity | ||
: function (a) { | ||
var s = __assign({}, a); | ||
for (var k in props) { | ||
s[k] = props[k].serialize(a[k]); | ||
} | ||
return s; | ||
}, props); | ||
}; | ||
exports.interface = exports.type; | ||
var PartialType = /** @class */ (function (_super) { | ||
__extends(PartialType, _super); | ||
function PartialType(name, is, validate, serialize, props) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.props = props; | ||
_this._tag = 'PartialType'; | ||
return _this; | ||
} | ||
return PartialType; | ||
}()); | ||
}(Type)); | ||
exports.PartialType = PartialType; | ||
exports.partial = function (props, name) { return new PartialType(props, name); }; | ||
exports.partial = function (props, name) { | ||
if (name === void 0) { name = "PartialType<" + getNameFromProps(props) + ">"; } | ||
var partials = {}; | ||
for (var k in props) { | ||
partials[k] = exports.union([props[k], undefinedType]); | ||
} | ||
var partial = exports.type(partials); | ||
return new PartialType(name, function (v) { return partial.is(v); }, function (s, c) { return partial.validate(s, c); }, useIdentity(props) | ||
? exports.identity | ||
: function (a) { | ||
var s = {}; | ||
for (var k in props) { | ||
var ak = a[k]; | ||
if (ak !== undefined) { | ||
s[k] = props[k].serialize(ak); | ||
} | ||
} | ||
return s; | ||
}, props); | ||
}; | ||
// | ||
// dictionaries | ||
// | ||
var DictionaryType = /** @class */ (function () { | ||
function DictionaryType(domain, codomain, name) { | ||
if (name === void 0) { name = "{ [key: " + domain.name + "]: " + codomain.name + " }"; } | ||
this.domain = domain; | ||
this.codomain = codomain; | ||
this.name = name; | ||
this._tag = 'DictionaryType'; | ||
this.validate = function (v, c) { | ||
return exports.Dictionary.validate(v, c).chain(function (o) { | ||
var t = {}; | ||
var errors = []; | ||
var changed = false; | ||
var _loop_3 = function (k) { | ||
var ok = o[k]; | ||
var domainValidation = domain.validate(k, c.concat(exports.getContextEntry(k, domain))); | ||
var codomainValidation = codomain.validate(ok, c.concat(exports.getContextEntry(k, codomain))); | ||
domainValidation.fold(function (error) { return pushAll(errors, error); }, function (vk) { | ||
changed = changed || vk !== k; | ||
k = vk; | ||
}); | ||
codomainValidation.fold(function (error) { return pushAll(errors, error); }, function (vok) { | ||
changed = changed || vok !== ok; | ||
t[k] = vok; | ||
}); | ||
}; | ||
for (var k in o) { | ||
_loop_3(k); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success((changed ? t : o)); | ||
}); | ||
}; | ||
var DictionaryType = /** @class */ (function (_super) { | ||
__extends(DictionaryType, _super); | ||
function DictionaryType(name, is, validate, serialize, codomain) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.codomain = codomain; | ||
_this._tag = 'DictionaryType'; | ||
return _this; | ||
} | ||
return DictionaryType; | ||
}()); | ||
}(Type)); | ||
exports.DictionaryType = DictionaryType; | ||
exports.dictionary = function (domain, codomain, name) { return new DictionaryType(domain, codomain, name); }; | ||
exports.dictionary = function (domain, codomain, name) { | ||
if (name === void 0) { name = "{ [K in " + domain.name + "]: " + codomain.name + " }"; } | ||
return new DictionaryType(name, function (v) { | ||
return exports.Dictionary.is(v) && Object.keys(v).every(function (k) { return domain.is(k) && codomain.is(v[k]); }); | ||
}, function (s, c) { | ||
return exports.Dictionary.validate(s, c).chain(function (o) { | ||
var a = {}; | ||
var errors = []; | ||
var changed = false; | ||
var _loop_3 = function (k) { | ||
var ok = o[k]; | ||
var domainValidation = domain.validate(k, c.concat(exports.getContextEntry(k, domain))); | ||
var codomainValidation = codomain.validate(ok, c.concat(exports.getContextEntry(k, codomain))); | ||
domainValidation.fold(function (e) { return pushAll(errors, e); }, function (vk) { | ||
changed = changed || vk !== k; | ||
k = vk; | ||
}); | ||
codomainValidation.fold(function (e) { return pushAll(errors, e); }, function (vok) { | ||
changed = changed || vok !== ok; | ||
a[k] = vok; | ||
}); | ||
}; | ||
for (var k in o) { | ||
_loop_3(k); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success((changed ? a : o)); | ||
}); | ||
}, domain.serialize === exports.identity && codomain.serialize === exports.identity | ||
? exports.identity | ||
: function (a) { | ||
var s = {}; | ||
for (var k in a) { | ||
s[domain.serialize(k)] = codomain.serialize(a[k]); | ||
} | ||
return s; | ||
}, codomain); | ||
}; | ||
// | ||
// unions | ||
// | ||
var UnionType = /** @class */ (function () { | ||
function UnionType(types, name) { | ||
if (name === void 0) { name = "(" + types.map(function (type) { return type.name; }).join(' | ') + ")"; } | ||
this.types = types; | ||
this.name = name; | ||
this._tag = 'UnionType'; | ||
this.validate = function (v, c) { | ||
var UnionType = /** @class */ (function (_super) { | ||
__extends(UnionType, _super); | ||
function UnionType(name, is, validate, serialize, types) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.types = types; | ||
_this._tag = 'UnionType'; | ||
return _this; | ||
} | ||
return UnionType; | ||
}(Type)); | ||
exports.UnionType = UnionType; | ||
exports.union = function (types, name) { | ||
if (name === void 0) { name = "(" + types.map(function (type) { return type.name; }).join(' | ') + ")"; } | ||
return new UnionType(name, function (v) { return types.some(function (type) { return type.is(v); }); }, function (s, c) { | ||
var errors = []; | ||
for (var i = 0; i < types.length; i++) { | ||
var type_2 = types[i]; | ||
var validation = type_2.validate(s, c.concat(exports.getContextEntry(String(i), type_2))); | ||
if (Either_1.isRight(validation)) { | ||
return validation; | ||
} | ||
else { | ||
pushAll(errors, validation.value); | ||
} | ||
} | ||
return exports.failures(errors); | ||
}, types.every(function (type) { return type.serialize === exports.identity; }) | ||
? exports.identity | ||
: function (a) { | ||
for (var i = 0; i < types.length; i++) { | ||
var validation = types[i].validate(v, c); | ||
if (Either_1.isRight(validation)) { | ||
return validation; | ||
var type_3 = types[i]; | ||
if (type_3.is(a)) { | ||
return type_3.serialize(a); | ||
} | ||
} | ||
return exports.failure(v, c); | ||
}; | ||
} | ||
return UnionType; | ||
}()); | ||
exports.UnionType = UnionType; | ||
exports.union = function (types, name) { return new UnionType(types, name); }; | ||
return a; | ||
}, types); | ||
}; | ||
// | ||
// intersections | ||
// | ||
var IntersectionType = /** @class */ (function () { | ||
function IntersectionType(types, name) { | ||
if (name === void 0) { name = "(" + types.map(function (type) { return type.name; }).join(' & ') + ")"; } | ||
this.types = types; | ||
this.name = name; | ||
this._tag = 'IntersectionType'; | ||
this.validate = function (v, c) { | ||
var t = v; | ||
var changed = false; | ||
var errors = []; | ||
for (var i = 0; i < types.length; i++) { | ||
var type_2 = types[i]; | ||
var validation = type_2.validate(t, c); | ||
validation.fold(function (error) { return pushAll(errors, error); }, function (vv) { | ||
changed = changed || vv !== t; | ||
t = vv; | ||
}); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success(changed ? t : v); | ||
}; | ||
var IntersectionType = /** @class */ (function (_super) { | ||
__extends(IntersectionType, _super); | ||
function IntersectionType(name, is, validate, serialize, types) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.types = types; | ||
_this._tag = 'IntersectionType'; | ||
return _this; | ||
} | ||
return IntersectionType; | ||
}()); | ||
}(Type)); | ||
exports.IntersectionType = IntersectionType; | ||
function intersection(types, name) { | ||
return new IntersectionType(types, name); | ||
if (name === void 0) { name = "(" + types.map(function (type) { return type.name; }).join(' & ') + ")"; } | ||
return new IntersectionType(name, function (v) { return types.every(function (type) { return type.is(v); }); }, function (s, c) { | ||
var a = s; | ||
var changed = false; | ||
var errors = []; | ||
for (var i = 0; i < types.length; i++) { | ||
var type_4 = types[i]; | ||
var validation = type_4.validate(a, c); | ||
validation.fold(function (e) { return pushAll(errors, e); }, function (va) { | ||
changed = changed || va !== a; | ||
a = va; | ||
}); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success(changed ? a : s); | ||
}, types.every(function (type) { return type.serialize === exports.identity; }) | ||
? exports.identity | ||
: function (a) { | ||
var s = a; | ||
for (var i = 0; i < types.length; i++) { | ||
var type_5 = types[i]; | ||
s = type_5.serialize(s); | ||
} | ||
return s; | ||
}, types); | ||
} | ||
@@ -427,34 +535,41 @@ exports.intersection = intersection; | ||
// | ||
var TupleType = /** @class */ (function () { | ||
function TupleType(types, name) { | ||
if (name === void 0) { name = "[" + types.map(function (type) { return type.name; }).join(', ') + "]"; } | ||
this.types = types; | ||
this.name = name; | ||
this._tag = 'TupleType'; | ||
this.validate = function (v, c) { | ||
return arrayType.validate(v, c).chain(function (as) { | ||
var t = []; | ||
var errors = []; | ||
var changed = false; | ||
var _loop_4 = function (i) { | ||
var a = as[i]; | ||
var type_3 = types[i]; | ||
var validation = type_3.validate(a, c.concat(exports.getContextEntry(String(i), type_3))); | ||
validation.fold(function (error) { return pushAll(errors, error); }, function (va) { | ||
changed = changed || va !== a; | ||
t.push(va); | ||
}); | ||
}; | ||
for (var i = 0; i < types.length; i++) { | ||
_loop_4(i); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success((changed ? t : as)); | ||
}); | ||
}; | ||
var TupleType = /** @class */ (function (_super) { | ||
__extends(TupleType, _super); | ||
function TupleType(name, is, validate, serialize, types) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.types = types; | ||
_this._tag = 'TupleType'; | ||
return _this; | ||
} | ||
return TupleType; | ||
}()); | ||
}(Type)); | ||
exports.TupleType = TupleType; | ||
function tuple(types, name) { | ||
return new TupleType(types, name); | ||
if (name === void 0) { name = "[" + types.map(function (type) { return type.name; }).join(', ') + "]"; } | ||
var len = types.length; | ||
return new TupleType(name, function (v) { return arrayType.is(v) && v.length === len && types.every(function (type, i) { return type.is(v[i]); }); }, function (s, c) { | ||
return arrayType.validate(s, c).chain(function (as) { | ||
var t = []; | ||
var errors = []; | ||
var changed = false; | ||
var _loop_4 = function (i) { | ||
var a = as[i]; | ||
var type_6 = types[i]; | ||
var validation = type_6.validate(a, c.concat(exports.getContextEntry(String(i), type_6))); | ||
validation.fold(function (e) { return pushAll(errors, e); }, function (va) { | ||
changed = changed || va !== a; | ||
t.push(va); | ||
}); | ||
}; | ||
for (var i = 0; i < len; i++) { | ||
_loop_4(i); | ||
} | ||
if (as.length > len) { | ||
errors.push(exports.getValidationError(as[len], c.concat(exports.getContextEntry(String(len), exports.never)))); | ||
} | ||
return errors.length ? exports.failures(errors) : exports.success((changed ? t : as)); | ||
}); | ||
}, types.every(function (type) { return type.serialize === exports.identity; }) | ||
? exports.identity | ||
: function (a) { return types.map(function (type, i) { return type.serialize(a[i]); }); }, types); | ||
} | ||
@@ -465,80 +580,88 @@ exports.tuple = tuple; | ||
// | ||
var ReadonlyType = /** @class */ (function () { | ||
function ReadonlyType(type, name) { | ||
if (name === void 0) { name = "Readonly<" + type.name + ">"; } | ||
this.type = type; | ||
this.name = name; | ||
this._tag = 'ReadonlyType'; | ||
this.validate = function (v, c) { | ||
return type.validate(v, c).map(function (x) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
return Object.freeze(x); | ||
} | ||
return x; | ||
}); | ||
}; | ||
var ReadonlyType = /** @class */ (function (_super) { | ||
__extends(ReadonlyType, _super); | ||
function ReadonlyType(name, is, validate, serialize, type) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.type = type; | ||
_this._tag = 'ReadonlyType'; | ||
return _this; | ||
} | ||
return ReadonlyType; | ||
}()); | ||
}(Type)); | ||
exports.ReadonlyType = ReadonlyType; | ||
exports.readonly = function (type, name) { return new ReadonlyType(type, name); }; | ||
exports.readonly = function (type, name) { | ||
if (name === void 0) { name = "Readonly<" + type.name + ">"; } | ||
return new ReadonlyType(name, type.is, function (s, c) { | ||
return type.validate(s, c).map(function (x) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
return Object.freeze(x); | ||
} | ||
return x; | ||
}); | ||
}, type.serialize === exports.identity ? exports.identity : type.serialize, type); | ||
}; | ||
// | ||
// readonlyArray | ||
// | ||
var ReadonlyArrayType = /** @class */ (function () { | ||
function ReadonlyArrayType(type, name) { | ||
if (name === void 0) { name = "ReadonlyArray<" + type.name + ">"; } | ||
this.type = type; | ||
this.name = name; | ||
this._tag = 'ReadonlyArrayType'; | ||
var arrayType = exports.array(type); | ||
this.validate = function (v, c) { | ||
return arrayType.validate(v, c).map(function (x) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
return Object.freeze(x); | ||
} | ||
return x; | ||
}); | ||
}; | ||
var ReadonlyArrayType = /** @class */ (function (_super) { | ||
__extends(ReadonlyArrayType, _super); | ||
function ReadonlyArrayType(name, is, validate, serialize, type) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.type = type; | ||
_this._tag = 'ReadonlyArrayType'; | ||
return _this; | ||
} | ||
return ReadonlyArrayType; | ||
}()); | ||
}(Type)); | ||
exports.ReadonlyArrayType = ReadonlyArrayType; | ||
exports.readonlyArray = function (type, name) { | ||
return new ReadonlyArrayType(type, name); | ||
if (name === void 0) { name = "ReadonlyArray<" + type.name + ">"; } | ||
var arrayType = exports.array(type); | ||
return new ReadonlyArrayType(name, function (v) { return arrayType.is(v); }, function (s, c) { | ||
return arrayType.validate(s, c).map(function (x) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
return Object.freeze(x); | ||
} | ||
else { | ||
return x; | ||
} | ||
}); | ||
}, arrayType.serialize, type); | ||
}; | ||
var StrictType = /** @class */ (function () { | ||
function StrictType(props, name) { | ||
this.props = props; | ||
this._tag = 'StrictType'; | ||
var loose = exports.type(props); | ||
this.name = name || "StrictType<" + loose.name + ">"; | ||
var len = Object.keys(props).length; | ||
this.validate = function (v, c) { | ||
return loose.validate(v, c).chain(function (o) { | ||
var keys = Object.getOwnPropertyNames(o); | ||
if (keys.length !== len) { | ||
var errors = []; | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
if (!props.hasOwnProperty(key)) { | ||
errors.push(exports.getValidationError(o[key], c.concat(exports.getContextEntry(key, exports.never)))); | ||
} | ||
} | ||
return errors.length ? exports.failures(errors) : exports.failure(o, c); | ||
} | ||
else { | ||
return exports.success(o); | ||
} | ||
}); | ||
}; | ||
var StrictType = /** @class */ (function (_super) { | ||
__extends(StrictType, _super); | ||
function StrictType(name, is, validate, serialize, props) { | ||
var _this = _super.call(this, name, is, validate, serialize) || this; | ||
_this.props = props; | ||
_this._tag = 'StrictType'; | ||
return _this; | ||
} | ||
return StrictType; | ||
}()); | ||
}(Type)); | ||
exports.StrictType = StrictType; | ||
/** Specifies that only the given interface properties are allowed */ | ||
function strict(props, name) { | ||
return new StrictType(props, name); | ||
if (name === void 0) { name = "StrictType<" + getNameFromProps(props) + ">"; } | ||
var loose = exports.type(props); | ||
var len = Object.keys(props).length; | ||
return new StrictType(name, function (v) { return loose.is(v) && Object.getOwnPropertyNames(v).every(function (k) { return props.hasOwnProperty(k); }); }, function (s, c) { | ||
return loose.validate(s, c).chain(function (o) { | ||
var keys = Object.getOwnPropertyNames(o); | ||
if (keys.length !== len) { | ||
var errors = []; | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
if (!props.hasOwnProperty(key)) { | ||
errors.push(exports.getValidationError(o[key], c.concat(exports.getContextEntry(key, exports.never)))); | ||
} | ||
} | ||
return errors.length ? exports.failures(errors) : exports.failure(o, c); | ||
} | ||
else { | ||
return exports.success(o); | ||
} | ||
}); | ||
}, loose.serialize, props); | ||
} | ||
exports.strict = strict; | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var index_1 = require("./index"); | ||
function stringify(value) { | ||
return typeof value === 'function' ? index_1.getFunctionName(value) : JSON.stringify(value); | ||
function stringify(v) { | ||
return typeof v === 'function' ? index_1.getFunctionName(v) : JSON.stringify(v); | ||
} | ||
@@ -13,4 +13,4 @@ function getContextPath(context) { | ||
} | ||
function getMessage(value, context) { | ||
return "Invalid value " + stringify(value) + " supplied to " + getContextPath(context); | ||
function getMessage(v, context) { | ||
return "Invalid value " + stringify(v) + " supplied to " + getContextPath(context); | ||
} | ||
@@ -17,0 +17,0 @@ function failure(es) { |
{ | ||
"name": "io-ts", | ||
"version": "0.8.2", | ||
"version": "0.9.0-dev.20171113", | ||
"description": "TypeScript compatible runtime type system for IO validation", | ||
@@ -5,0 +5,0 @@ "files": ["lib"], |
# The idea | ||
A value of type `Type<T>` (called "runtime type") is the runtime representation of the static type `T`: | ||
A value of type `Type<S, A>` (called "runtime type") is the runtime representation of the static type `A`: | ||
```js | ||
export interface Type<A> { | ||
class Type<S, A> { | ||
readonly _A: A | ||
readonly name: string | ||
readonly validate: Validate<A> | ||
readonly _S: S | ||
constructor( | ||
readonly name: string, | ||
readonly is: Is<A>, | ||
readonly validate: Validate<S, A>, | ||
readonly serialize: Serialize<S, A> | ||
) {} | ||
} | ||
``` | ||
where `Validate<T>` is a specific validation function for `T` | ||
where `Validate<A>` is a specific validation function for the type `A` | ||
```js | ||
type Validate<T> = (value: any, context: Context) => Either<Array<ValidationError>, T>; | ||
export interface ContextEntry { | ||
readonly key: string | ||
readonly type: Any | NeverType | ||
} | ||
export type Context = Array<ContextEntry> | ||
export interface ValidationError { | ||
readonly value: any | ||
readonly context: Context | ||
} | ||
export type Errors = Array<ValidationError> | ||
export type Validation<A> = Either<Errors, A> | ||
export type Is<A> = (v: any) => v is A | ||
export type Validate<S, A> = (s: S, context: Context) => Validation<A> | ||
export type Serialize<S, A> = (a: A) => S | ||
``` | ||
@@ -28,11 +46,14 @@ | ||
export const string: t.Type<string> = { | ||
_A: t._A, | ||
name: 'string', | ||
validate: (value, context) => (typeof value === 'string' ? t.success(value) : t.failure<string>(value, context)) | ||
export class StringType extends Type<any, string> { | ||
constructor() { | ||
super( | ||
'string', | ||
(v): v is string => typeof v === 'string', | ||
(s, c) => (this.is(s) ? success(s) : failure(s, c)), | ||
a => a | ||
) | ||
} | ||
} | ||
``` | ||
Note: The `_A` field contains a dummy value and is useful to extract a static type from the runtime type (see the ["TypeScript integration"](#typescript-integration) section below) | ||
A runtime type can be used to validate an object in memory (for example an API payload) | ||
@@ -114,3 +135,3 @@ | ||
Note that recursive types can't be inferred | ||
Recursive types can't be inferred by TypeScript so you must provide the static type as a hint | ||
@@ -152,3 +173,3 @@ ```js | ||
| dictionary of any | `{ [key: string]: any }` | `t.Dictionary` | | ||
| dictionary of type | `{ [key: A]: B }` | `t.dictionary(A, B)` | | ||
| dictionary of type | `{ [K in A]: B }` | `t.dictionary(A, B)` | | ||
| function | `Function` | `t.Function` | | ||
@@ -167,4 +188,2 @@ | literal | `'s'` | `t.literal('s')` | | ||
| refinement | ✘ | `t.refinement(A, predicate)` | | ||
| map | ✘ | `t.map(f, type)` | | ||
| prism | ✘ | `t.prism(type, getOption)` | | ||
| strict | ✘ | `t.strict({ name: t.string })` | | ||
@@ -229,12 +248,13 @@ | ||
// returns a Date from an ISO string | ||
const DateFromString: t.Type<Date> = { | ||
_A: t._A, | ||
name: 'DateFromString', | ||
validate: (v, c) => | ||
// represents a Date from an ISO string | ||
const DateFromString = new t.Type<any, Date>( | ||
'DateFromString', | ||
(v): v is Date => v instanceof Date, | ||
(v, c) => | ||
t.string.validate(v, c).chain(s => { | ||
const d = new Date(s) | ||
return isNaN(d.getTime()) ? t.failure<Date>(s, c) : t.success(d) | ||
}) | ||
} | ||
return isNaN(d.getTime()) ? t.failure(s, c) : t.success(d) | ||
}), | ||
a => a.toISOString() | ||
) | ||
@@ -244,6 +264,6 @@ const s = new Date(1973, 10, 30).toISOString() | ||
t.validate(s, DateFromString) | ||
// => Right(Date(..)) | ||
// right(new Date('1973-11-29T23:00:00.000Z')) | ||
t.validate('foo', DateFromString) | ||
// => Left( 'Invalid value "foo" supplied to : DateFromString' ) | ||
// left(errors...) | ||
``` | ||
@@ -262,7 +282,4 @@ | ||
```ts | ||
export function maybe<RT extends t.Any>( | ||
type: RT, | ||
name?: string | ||
): t.UnionType<[RT, typeof t.null], t.TypeOf<RT> | null> { | ||
return t.union([type, t.null], name) | ||
export function maybe<RT extends t.Any>(type: RT, name?: string): t.UnionType<[RT, t.NullType]> { | ||
return t.union<[RT, t.NullType]>([type, t.null], name) | ||
} | ||
@@ -298,3 +315,3 @@ ``` | ||
```ts | ||
export function brand<T, B extends string>(type: t.Type<T>, brand: B): t.Type<T & { readonly __brand: B }> { | ||
export function brand<S, A, B extends string>(type: t.Type<S, A>, _: B): t.Type<S, A & { readonly __brand: B }> { | ||
return type as any | ||
@@ -333,9 +350,10 @@ } | ||
function unsafeValidate<T>(value: any, type: t.Type<T>): T { | ||
export function unsafeValidate<S, A>(value: any, type: t.Type<S, A>): A { | ||
if (process.env.NODE_ENV !== 'production') { | ||
return t.validate(value, type).fold(errors => { | ||
throw new Error(failure(errors).join('\n')) | ||
}, x => x) | ||
}, t.identity) | ||
} | ||
return value as T | ||
// unsafe cast | ||
return value as A | ||
} | ||
@@ -342,0 +360,0 @@ ``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
83283
931
383
1