Comparing version 0.9.6 to 0.9.7
@@ -16,2 +16,7 @@ # Changelog | ||
# 0.9.7 | ||
* **New Feature** | ||
* add `taggedUnion` combinator (@gcanti, @sledorze) | ||
# 0.9.6 | ||
@@ -18,0 +23,0 @@ |
@@ -245,2 +245,14 @@ import { Either } from 'fp-ts/lib/Either'; | ||
export declare const strict: <P extends Props>(props: P, name?: string) => StrictType<P, InterfaceOf<P>>; | ||
export declare type TaggedProps<Tag extends string> = { | ||
[K in Tag]: LiteralType<any>; | ||
}; | ||
export interface TaggedRefinement<Tag extends string, A> extends RefinementType<Tagged<Tag>, mixed, A> { | ||
} | ||
export interface TaggedUnion<Tag extends string, A> extends UnionType<Array<Tagged<Tag>>, A> { | ||
} | ||
export declare type TaggedIntersectionArgument<Tag extends string> = [Tagged<Tag>] | [Tagged<Tag>, Any] | [Any, Tagged<Tag>] | [Tagged<Tag>, Any, Any] | [Any, Tagged<Tag>, Any] | [Any, Any, Tagged<Tag>] | [Tagged<Tag>, Any, Any, Any] | [Any, Tagged<Tag>, Any, Any] | [Any, Any, Tagged<Tag>, Any] | [Any, Any, Any, Tagged<Tag>] | [Tagged<Tag>, Any, Any, Any, Any] | [Any, Tagged<Tag>, Any, Any, Any] | [Any, Any, Tagged<Tag>, Any, Any] | [Any, Any, Any, Tagged<Tag>, Any] | [Any, Any, Any, Any, Tagged<Tag>]; | ||
export interface TaggedIntersection<Tag extends string, A> extends IntersectionType<TaggedIntersectionArgument<Tag>, A> { | ||
} | ||
export declare type Tagged<Tag extends string, A = any> = InterfaceType<TaggedProps<Tag>, A> | StrictType<TaggedProps<Tag>, A> | TaggedRefinement<Tag, A> | TaggedUnion<Tag, A> | TaggedIntersection<Tag, A>; | ||
export declare const taggedUnion: <Tag extends string, RTS extends Tagged<Tag, any>[]>(tag: Tag, types: RTS, name?: string) => UnionType<RTS, RTS["_A"]["_A"]>; | ||
export { nullType as null, undefinedType as undefined, arrayType as Array, type as interface }; |
@@ -709,2 +709,78 @@ "use strict"; | ||
}; | ||
var isTagged = function (tag) { | ||
var f = function (type) { | ||
if (type instanceof InterfaceType || type instanceof StrictType) { | ||
return type.props.hasOwnProperty(tag); | ||
} | ||
else if (type instanceof IntersectionType) { | ||
return type.types.some(f); | ||
} | ||
else if (type instanceof UnionType) { | ||
return type.types.every(f); | ||
} | ||
else if (type instanceof RefinementType) { | ||
return f(type.type); | ||
} | ||
else { | ||
return false; | ||
} | ||
}; | ||
return f; | ||
}; | ||
var findTagged = function (tag, types) { | ||
var len = types.length; | ||
var is = isTagged(tag); | ||
var i = 0; | ||
for (; i < len - 1; i++) { | ||
var type_7 = types[i]; | ||
if (is(type_7)) { | ||
return type_7; | ||
} | ||
} | ||
return types[i]; | ||
}; | ||
var getTagValue = function (tag) { | ||
var f = function (type) { | ||
switch (type._tag) { | ||
case 'InterfaceType': | ||
case 'StrictType': | ||
return type.props[tag].value; | ||
case 'IntersectionType': | ||
return f(findTagged(tag, type.types)); | ||
case 'UnionType': | ||
return f(type.types[0]); | ||
case 'RefinementType': | ||
return f(type.type); | ||
} | ||
}; | ||
return f; | ||
}; | ||
exports.taggedUnion = function (tag, types, name) { | ||
if (name === void 0) { name = "(" + types.map(function (type) { return type.name; }).join(' | ') + ")"; } | ||
var tagValue2Index = {}; | ||
var tagValues = {}; | ||
var len = types.length; | ||
var get = getTagValue(tag); | ||
for (var i = 0; i < len; i++) { | ||
var value = get(types[i]); | ||
tagValue2Index[value] = i; | ||
tagValues[value] = null; | ||
} | ||
var TagValue = exports.keyof(tagValues); | ||
return new UnionType(name, function (v) { | ||
if (!exports.Dictionary.is(v)) { | ||
return false; | ||
} | ||
var tagValue = v[tag]; | ||
return TagValue.is(tagValue) && types[tagValue2Index[tagValue]].is(v); | ||
}, function (s, c) { | ||
return exports.Dictionary.validate(s, c).chain(function (d) { | ||
return TagValue.validate(d[tag], exports.appendContext(c, tag, TagValue)).chain(function (tagValue) { | ||
var i = tagValue2Index[tagValue]; | ||
var type = types[i]; | ||
return type.validate(d, exports.appendContext(c, String(i), type)); | ||
}); | ||
}); | ||
}, types.every(function (type) { return type.serialize === exports.identity; }) ? exports.identity : function (a) { return types[tagValue2Index[a[tag]]].serialize(a); }, types); | ||
}; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "io-ts", | ||
"version": "0.9.6", | ||
"version": "0.9.7", | ||
"description": "TypeScript compatible runtime type system for IO validation", | ||
@@ -5,0 +5,0 @@ "files": ["lib"], |
@@ -181,3 +181,3 @@ # The idea | ||
| tuple | `[ A, B ]` | `[ A, B ]` | `t.tuple([ A, B ])` | | ||
| union | `A \| B` | `A \| B` | `t.union([ A, B ])` | | ||
| union | `A \| B` | `A \| B` | `t.union([ A, B ])` or `t.taggedUnion(tag, [ A, B ])` | | ||
| intersection | `A & B` | `A & B` | `t.intersection([ A, B ])` | | ||
@@ -189,2 +189,22 @@ | keyof | `keyof M` | `$Keys<M>` | `t.keyof(M)` | | ||
# Tagged unions | ||
If you are encoding tagged unions, instead of the general purpose `union` combinator, you may want to use the | ||
`taggedUnion` combinator in order to get better performances | ||
```ts | ||
const A = t.type({ | ||
tag: t.literal('A'), | ||
foo: t.string | ||
}) | ||
const B = t.type({ | ||
tag: t.literal('B'), | ||
bar: t.number | ||
}) | ||
// the actual presence of the tag is statically checked | ||
const U = t.taggedUnion('tag', [A, B]) | ||
``` | ||
# Refinements | ||
@@ -191,0 +211,0 @@ |
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
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
113487
1092
405