From 81cb096006c7560b005524bf3aae614b1cc6b22f Mon Sep 17 00:00:00 2001 From: gcanti Date: Sat, 4 Mar 2017 09:20:47 +0100 Subject: [PATCH] remove maybe combinator --- README.md | 22 +++++++++++++++++++++- src/index.ts | 18 ------------------ test/maybe.ts | 32 -------------------------------- test/recursion.ts | 12 +++++------- typings-checker/index.ts | 12 ------------ 5 files changed, 26 insertions(+), 70 deletions(-) delete mode 100644 test/maybe.ts diff --git a/README.md b/README.md index 02372a83c..4db31322b 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ This package exports two default reporters Example ```js -import { PathReporter, ThrowReporter } from '../src/reporters/default' +import { PathReporter, ThrowReporter } from 'io-ts/reporters/default' const validation = t.validate({"name":"Giulio"}, Person) @@ -146,6 +146,26 @@ import * as t from 'io-ts' | keyof | `keyof M` | `t.keyof(M)` | | recursive types | | `t.recursion(name, definition)` | +# Custom combinators + +You can define your own combinators. Let's see some interesting examples + +## The `maybe` combinator + +```ts +export function maybe(type: RT, name?: string): t.UnionType<[RT, typeof t.null], t.TypeOf | null> { + return t.union([type, t.null], name) +} +``` + +## The `brand` combinator + +```ts +export function brand(type: t.Type, brand: B): t.Type { + return type as any +} +``` + # Known issues Due to an upstream [bug](https://github.com/Microsoft/TypeScript/issues/14041), VS Code might display weird types for nested interfaces diff --git a/src/index.ts b/src/index.ts index 349e287b0..a4b597f9d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -188,24 +188,6 @@ export function recursion(name: string, definition: (self: Any) => Any): Type return Result } -// -// maybes -// - -export class MaybeType extends Type | null> { - constructor(name: string, validate: Validate | null>, public readonly type: RT) { - super(name, validate) - } -} - -export function maybe(type: RT, name?: string): MaybeType { - return new MaybeType( - name || `(${getTypeName(type)} | null)`, - (v, c) => v === null ? success(v) : type.validate(v, c), - type - ) -} - // // arrays // diff --git a/test/maybe.ts b/test/maybe.ts deleted file mode 100644 index 4a605fec2..000000000 --- a/test/maybe.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as t from '../src/index' -import { - assertSuccess, - assertFailure, - assertStrictEqual -} from './helpers' - -describe('maybe', () => { - - it('should succeed validating a valid value', () => { - const T = t.maybe(t.number) - assertSuccess(t.validate(null, T)) - assertSuccess(t.validate(1, T)) - }) - - it('should return the same reference if validation succeeded', () => { - const T = t.maybe(t.Dictionary) - const value = {} - assertStrictEqual(t.validate(value, T), value) - }) - - it('should fail validating an invalid value', () => { - const T = t.maybe(t.number) - assertFailure(t.validate(undefined, T), [ - 'Invalid value undefined supplied to : (number | null)' - ]) - assertFailure(t.validate('s', T), [ - 'Invalid value "s" supplied to : (number | null)' - ]) - }) - -}) diff --git a/test/recursion.ts b/test/recursion.ts index 4d3a6faec..89262fabb 100644 --- a/test/recursion.ts +++ b/test/recursion.ts @@ -10,7 +10,7 @@ describe('recursion', () => { it('should succeed validating a valid value', () => { const T = t.recursion('T', self => t.interface({ a: t.number, - b: t.maybe(self) + b: t.union([self, t.undefined, t.null]) })) assertSuccess(t.validate({ a: 1, b: null }, T)) assertSuccess(t.validate({ a: 1, b: { a: 2, b: null } }, T)) @@ -19,7 +19,7 @@ describe('recursion', () => { it('should return the same reference if validation succeeded', () => { const T = t.recursion('T', self => t.interface({ a: t.number, - b: t.maybe(self) + b: t.union([self, t.undefined, t.null]) })) const value = { a: 1, b: { a: 2, b: null } } assertStrictEqual(t.validate(value, T), value) @@ -28,18 +28,16 @@ describe('recursion', () => { it('should fail validating an invalid value', () => { const T = t.recursion('T', self => t.interface({ a: t.number, - b: t.maybe(self) + b: t.union([self, t.undefined, t.null]) })) assertFailure(t.validate(1, T), [ 'Invalid value 1 supplied to : T' ]) assertFailure(t.validate({}, T), [ - 'Invalid value undefined supplied to : T/a: number', - 'Invalid value undefined supplied to : T/b: (T | null)' + 'Invalid value undefined supplied to : T/a: number' ]) assertFailure(t.validate({ a: 1, b: {} }, T), [ - 'Invalid value undefined supplied to : T/b: (T | null)/a: number', - 'Invalid value undefined supplied to : T/b: (T | null)/b: (T | null)' + 'Invalid value {} supplied to : T/b: (T | undefined | null)' ]) }) diff --git a/typings-checker/index.ts b/typings-checker/index.ts index 69161c86a..288336753 100644 --- a/typings-checker/index.ts +++ b/typings-checker/index.ts @@ -45,18 +45,6 @@ const R1 = t.refinement(t.number, n => n % 2 === 0) ;('s' as TypeOf) ;(2 as TypeOf) -// -// maybes -// - -const M1 = t.maybe(t.number) -// $ExpectError Type 'string' cannot be converted to type 'number | null' -;('s' as TypeOf) -// $ExpectError Type 'undefined' cannot be converted to type 'number | null' -;(undefined as TypeOf) -;(2 as TypeOf) -;(null as TypeOf) - // // arrays //