Comparing version 1.8.6 to 1.9.0
@@ -17,2 +17,9 @@ # Changelog | ||
# 1.9.0 | ||
- **New Feature** | ||
- `union` is now able to detect and optimize tagged unions (@gcanti) | ||
- **Deprecation** | ||
- deprecate `taggedUnion` in favour of `union` (@gcanti) | ||
# 1.8.6 | ||
@@ -19,0 +26,0 @@ |
@@ -678,2 +678,3 @@ import { Either } from 'fp-ts/lib/Either'; | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
@@ -686,7 +687,12 @@ export declare class TaggedUnionType<Tag extends string, CS extends Array<Mixed>, A = any, O = A, I = unknown> extends UnionType<CS, A, O, I> { | ||
* @since 1.5.3 | ||
* @deprecated | ||
*/ | ||
export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Array<Mixed>]> extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> { | ||
export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Array<Mixed>]>// tslint:disable-next-line: deprecation | ||
extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> { | ||
} | ||
/** | ||
* Use `union` instead | ||
* | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
@@ -871,3 +877,4 @@ export declare const taggedUnion: <Tag extends string, CS extends [Mixed, Mixed, ...Mixed[]]>(tag: Tag, codecs: CS, name?: string) => TaggedUnionC<Tag, CS>; | ||
*/ | ||
export interface StrictC<P extends Props> extends StrictType<P, { | ||
export interface StrictC<P extends Props>// tslint:disable-next-line: deprecation | ||
extends StrictType<P, { | ||
[K in keyof P]: TypeOf<P[K]>; | ||
@@ -906,3 +913,4 @@ }, { | ||
*/ | ||
export interface TaggedIntersection<Tag extends string, A, O = A> extends IntersectionType<TaggedIntersectionArgument<Tag>, A, O> { | ||
export interface TaggedIntersection<Tag extends string, A, O = A>// tslint:disable-next-line: deprecation | ||
extends IntersectionType<TaggedIntersectionArgument<Tag>, A, O> { | ||
} | ||
@@ -909,0 +917,0 @@ /** |
484
es6/index.js
@@ -117,12 +117,6 @@ var __extends = (this && this.__extends) || (function () { | ||
var isUnknownCodec = getIsCodec('UnknownType'); | ||
// tslint:disable-next-line: deprecation | ||
var isAnyCodec = getIsCodec('AnyType'); | ||
var isLiteralCodec = getIsCodec('LiteralType'); | ||
var isInterfaceCodec = getIsCodec('InterfaceType'); | ||
var isPartialCodec = getIsCodec('PartialType'); | ||
var isStrictCodec = getIsCodec('StrictType'); | ||
var isIntersectionCodec = getIsCodec('IntersectionType'); | ||
var isUnionCodec = getIsCodec('UnionType'); | ||
var isExactCodec = getIsCodec('ExactType'); | ||
var isRefinementCodec = getIsCodec('RefinementType'); | ||
var isRecursiveCodec = getIsCodec('RecursiveType'); | ||
// | ||
@@ -303,2 +297,3 @@ // basic types | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
export var Function = new FunctionType(); | ||
@@ -324,2 +319,3 @@ /** | ||
export var brand = function (codec, predicate, name) { | ||
// tslint:disable-next-line: deprecation | ||
return refinement(codec, predicate, name); | ||
@@ -413,11 +409,2 @@ }; | ||
var Self = new RecursiveType(name, function (u) { return runDefinition().is(u); }, function (u, c) { return runDefinition().validate(u, c); }, function (a) { return runDefinition().encode(a); }, runDefinition); | ||
var indexRecordCache; | ||
Self.getIndexRecord = function () { | ||
if (!indexRecordCache) { | ||
isRecursiveCodecIndexable = false; | ||
indexRecordCache = getCodecIndexRecord(definition(Self), Self, Self); | ||
isRecursiveCodecIndexable = true; | ||
} | ||
return indexRecordCache; | ||
}; | ||
return Self; | ||
@@ -491,4 +478,4 @@ }; | ||
}; | ||
var useIdentity = function (codecs, len) { | ||
for (var i = 0; i < len; i++) { | ||
var useIdentity = function (codecs) { | ||
for (var i = 0; i < codecs.length; i++) { | ||
if (codecs[i].encode !== identity) { | ||
@@ -557,3 +544,3 @@ return false; | ||
return errors.length > 0 ? failures(errors) : success(a); | ||
}, useIdentity(types, len) | ||
}, useIdentity(types) | ||
? identity | ||
@@ -637,3 +624,3 @@ : function (a) { | ||
return errors.length > 0 ? failures(errors) : success(a); | ||
}, useIdentity(types, len) | ||
}, useIdentity(types) | ||
? identity | ||
@@ -753,26 +740,71 @@ : function (a) { | ||
if (name === void 0) { name = getUnionName(codecs); } | ||
var len = codecs.length; | ||
return new UnionType(name, function (u) { return codecs.some(function (type) { return type.is(u); }); }, function (u, c) { | ||
var errors = []; | ||
for (var i = 0; i < len; i++) { | ||
var type_3 = codecs[i]; | ||
var validation = type_3.validate(u, appendContext(c, String(i), type_3, u)); | ||
if (validation.isRight()) { | ||
return validation; | ||
var index = getIndex(codecs); | ||
if (index !== undefined && codecs.length > 0) { | ||
var tag_1 = index[0], groups_1 = index[1]; | ||
var len_1 = groups_1.length; | ||
var find_1 = function (value) { | ||
for (var i = 0; i < len_1; i++) { | ||
if (groups_1[i].indexOf(value) !== -1) { | ||
return i; | ||
} | ||
} | ||
pushAll(errors, validation.value); | ||
} | ||
return errors.length > 0 ? failures(errors) : failure(u, c); | ||
}, useIdentity(codecs, len) | ||
? identity | ||
: function (a) { | ||
for (var i = 0; i < len; i++) { | ||
return undefined; | ||
}; | ||
// tslint:disable-next-line: deprecation | ||
return new TaggedUnionType(name, function (u) { | ||
if (!UnknownRecord.is(u)) { | ||
return false; | ||
} | ||
var i = find_1(u[tag_1]); | ||
return i !== undefined ? codecs[i].is(u) : false; | ||
}, function (u, c) { | ||
var dictionaryResult = UnknownRecord.validate(u, c); | ||
if (dictionaryResult.isLeft()) { | ||
return dictionaryResult; | ||
} | ||
var r = dictionaryResult.value; | ||
var i = find_1(r[tag_1]); | ||
if (i === undefined) { | ||
return failure(u, c); | ||
} | ||
var codec = codecs[i]; | ||
return codec.validate(r, appendContext(c, String(i), codec, r)); | ||
}, useIdentity(codecs) | ||
? identity | ||
: function (a) { | ||
var i = find_1(a[tag_1]); | ||
if (i === undefined) { | ||
// https://github.com/gcanti/io-ts/pull/305 | ||
throw new Error("no codec found to encode value in union codec " + name); | ||
} | ||
else { | ||
return codecs[i].encode(a); | ||
} | ||
}, codecs, tag_1); | ||
} | ||
else { | ||
return new UnionType(name, function (u) { return codecs.some(function (type) { return type.is(u); }); }, function (u, c) { | ||
var errors = []; | ||
for (var i = 0; i < codecs.length; i++) { | ||
var codec = codecs[i]; | ||
if (codec.is(a)) { | ||
return codec.encode(a); | ||
var validation = codec.validate(u, appendContext(c, String(i), codec, u)); | ||
if (validation.isRight()) { | ||
return validation; | ||
} | ||
pushAll(errors, validation.value); | ||
} | ||
// https://github.com/gcanti/io-ts/pull/305 | ||
throw new Error("no codec found to encode value in union type " + name); | ||
}, codecs); | ||
return failures(errors); | ||
}, useIdentity(codecs) | ||
? identity | ||
: function (a) { | ||
for (var _i = 0, codecs_1 = codecs; _i < codecs_1.length; _i++) { | ||
var codec = codecs_1[_i]; | ||
if (codec.is(a)) { | ||
return codec.encode(a); | ||
} | ||
} | ||
// https://github.com/gcanti/io-ts/pull/305 | ||
throw new Error("no codec found to encode value in union type " + name); | ||
}, codecs); | ||
} | ||
}; | ||
@@ -860,4 +892,4 @@ /** | ||
var a = us[i]; | ||
var type_4 = codecs[i]; | ||
var validation = type_4.validate(a, appendContext(c, String(i), type_4, a)); | ||
var type_3 = codecs[i]; | ||
var validation = type_3.validate(a, appendContext(c, String(i), type_3, a)); | ||
if (validation.isLeft()) { | ||
@@ -878,3 +910,3 @@ pushAll(errors, validation.value); | ||
return errors.length > 0 ? failures(errors) : success(as); | ||
}, useIdentity(codecs, len) ? identity : function (a) { return codecs.map(function (type, i) { return type.encode(a[i]); }); }, codecs); | ||
}, useIdentity(codecs) ? identity : function (a) { return codecs.map(function (type, i) { return type.encode(a[i]); }); }, codecs); | ||
} | ||
@@ -945,181 +977,15 @@ /** | ||
}; | ||
/** @internal */ | ||
export var emptyIndexRecord = {}; | ||
var monoidIndexRecord = { | ||
concat: function (a, b) { | ||
var _a; | ||
if (a === monoidIndexRecord.empty) { | ||
return b; | ||
} | ||
if (b === monoidIndexRecord.empty) { | ||
return a; | ||
} | ||
var r = cloneIndexRecord(a); | ||
for (var k in b) { | ||
if (r.hasOwnProperty(k)) { | ||
(_a = r[k]).push.apply(_a, b[k]); | ||
} | ||
else { | ||
r[k] = b[k]; | ||
} | ||
} | ||
return r; | ||
}, | ||
empty: emptyIndexRecord | ||
}; | ||
var isIndexRecordEmpty = function (a) { | ||
for (var _ in a) { | ||
return false; | ||
} | ||
return true; | ||
}; | ||
var foldMapIndexRecord = function (as, f) { | ||
return as.reduce(function (acc, a) { return monoidIndexRecord.concat(acc, f(a)); }, monoidIndexRecord.empty); | ||
}; | ||
var cloneIndexRecord = function (a) { | ||
var r = {}; | ||
for (var k in a) { | ||
r[k] = a[k].slice(); | ||
} | ||
return r; | ||
}; | ||
var updateindexRecordOrigin = function (origin, indexRecord) { | ||
var r = {}; | ||
for (var k in indexRecord) { | ||
r[k] = indexRecord[k].map(function (_a) { | ||
var v = _a[0], _ = _a[1], id = _a[2]; | ||
return [v, origin, id]; | ||
}); | ||
} | ||
return r; | ||
}; | ||
var getCodecIndexRecord = function (codec, origin, id) { | ||
if (isInterfaceCodec(codec) || isStrictCodec(codec)) { | ||
var interfaceIndex = {}; | ||
for (var k in codec.props) { | ||
var prop = codec.props[k]; | ||
if (isLiteralCodec(prop)) { | ||
var value = prop.value; | ||
interfaceIndex[k] = [[value, origin, id]]; | ||
} | ||
} | ||
return interfaceIndex; | ||
} | ||
if (isIntersectionCodec(codec)) { | ||
return foldMapIndexRecord(codec.types, function (type) { return getCodecIndexRecord(type, origin, codec); }); | ||
} | ||
if (isUnionCodec(codec)) { | ||
return foldMapIndexRecord(codec.types, function (type) { return getCodecIndexRecord(type, origin, type); }); | ||
} | ||
if (isExactCodec(codec) || isRefinementCodec(codec)) { | ||
return getCodecIndexRecord(codec.type, origin, codec); | ||
} | ||
if (isRecursiveCodec(codec)) { | ||
var indexRecord = codec.getIndexRecord(); | ||
if (codec !== origin) { | ||
return updateindexRecordOrigin(origin, indexRecord); | ||
} | ||
return indexRecord; | ||
} | ||
return monoidIndexRecord.empty; | ||
}; | ||
var isRecursiveCodecIndexable = true; | ||
var isIndexableCodec = function (codec) { | ||
return (((isInterfaceCodec(codec) || isStrictCodec(codec)) && | ||
Object.keys(codec.props).some(function (key) { return isLiteralCodec(codec.props[key]); })) || | ||
((isExactCodec(codec) || isRefinementCodec(codec)) && isIndexableCodec(codec.type)) || | ||
(isIntersectionCodec(codec) && codec.types.some(isIndexableCodec)) || | ||
(isUnionCodec(codec) && codec.types.every(isIndexableCodec)) || | ||
(isRecursiveCodecIndexable && isRecursiveCodec(codec))); | ||
}; | ||
/** | ||
* @internal | ||
*/ | ||
export var getIndexRecord = function (codecs) { | ||
var len = codecs.length; | ||
if (len === 0 || !codecs.every(isIndexableCodec)) { | ||
return monoidIndexRecord.empty; | ||
} | ||
var firstCodec = codecs[0]; | ||
var ir = cloneIndexRecord(getCodecIndexRecord(firstCodec, firstCodec, firstCodec)); | ||
for (var i = 1; i < len; i++) { | ||
var codec = codecs[i]; | ||
var cir = getCodecIndexRecord(codec, codec, codec); | ||
for (var k in ir) { | ||
if (cir.hasOwnProperty(k)) { | ||
var is = ir[k]; | ||
var cis = cir[k]; | ||
var _loop_1 = function (j) { | ||
var indexItem = cis[j]; | ||
var index = is.findIndex(function (_a) { | ||
var v = _a[0]; | ||
return v === indexItem[0]; | ||
}); | ||
if (index === -1) { | ||
is.push(indexItem); | ||
} | ||
else if (indexItem[2] !== is[index][2]) { | ||
delete ir[k]; | ||
return "break"; | ||
} | ||
}; | ||
for (var j = 0; j < cis.length; j++) { | ||
var state_1 = _loop_1(j); | ||
if (state_1 === "break") | ||
break; | ||
} | ||
} | ||
else { | ||
delete ir[k]; | ||
} | ||
} | ||
} | ||
return isIndexRecordEmpty(ir) ? monoidIndexRecord.empty : ir; | ||
}; | ||
var getTaggedUnion = function (index, tag, codecs, name) { | ||
var len = codecs.length; | ||
var indexWithPosition = index.map(function (_a) { | ||
var v = _a[0], origin = _a[1]; | ||
return [ | ||
v, | ||
codecs.findIndex(function (codec) { return codec === origin; }) | ||
]; | ||
}); | ||
var findIndex = function (tagValue) { | ||
for (var i = 0; i < indexWithPosition.length; i++) { | ||
var _a = indexWithPosition[i], value = _a[0], position = _a[1]; | ||
if (value === tagValue) { | ||
return position; | ||
} | ||
} | ||
}; | ||
var isTagValue = function (u) { return findIndex(u) !== undefined; }; | ||
return new TaggedUnionType(name, function (u) { | ||
if (!UnknownRecord.is(u)) { | ||
return false; | ||
} | ||
var tagValue = u[tag]; | ||
var index = findIndex(tagValue); | ||
return index !== undefined ? codecs[index].is(u) : false; | ||
}, function (u, c) { | ||
var dictionaryResult = UnknownRecord.validate(u, c); | ||
if (dictionaryResult.isLeft()) { | ||
return dictionaryResult; | ||
} | ||
var d = dictionaryResult.value; | ||
var tagValue = d[tag]; | ||
if (!isTagValue(tagValue)) { | ||
return failure(u, c); | ||
} | ||
var index = findIndex(tagValue); | ||
var codec = codecs[index]; | ||
return codec.validate(d, appendContext(c, String(index), codec, d)); | ||
}, useIdentity(codecs, len) ? identity : function (a) { return codecs[findIndex(a[tag])].encode(a); }, codecs, tag); | ||
}; | ||
/** | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
var TaggedUnionType = /** @class */ (function (_super) { | ||
__extends(TaggedUnionType, _super); | ||
function TaggedUnionType(name, is, validate, encode, codecs, tag) { | ||
function TaggedUnionType(name, | ||
// tslint:disable-next-line: deprecation | ||
is, | ||
// tslint:disable-next-line: deprecation | ||
validate, | ||
// tslint:disable-next-line: deprecation | ||
encode, codecs, tag) { | ||
var _this = _super.call(this, name, is, validate, encode, codecs) /* istanbul ignore next */ // <= workaround for https://github.com/Microsoft/TypeScript/issues/13455 | ||
@@ -1134,15 +1000,21 @@ || this; | ||
/** | ||
* Use `union` instead | ||
* | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
export var taggedUnion = function (tag, codecs, name) { | ||
export var taggedUnion = function (tag, codecs, name | ||
// tslint:disable-next-line: deprecation | ||
) { | ||
if (name === void 0) { name = getUnionName(codecs); } | ||
var indexRecord = getIndexRecord(codecs); | ||
if (!indexRecord.hasOwnProperty(tag)) { | ||
if (isRecursiveCodecIndexable && codecs.length > 0) { | ||
console.warn("[io-ts] Cannot build a tagged union for " + name + ", returning a de-optimized union"); | ||
} | ||
var U = union(codecs, name); | ||
var U = union(codecs, name); | ||
// tslint:disable-next-line: deprecation | ||
if (U instanceof TaggedUnionType) { | ||
return U; | ||
} | ||
else { | ||
console.warn("[io-ts] Cannot build a tagged union for " + name + ", returning a de-optimized union"); | ||
// tslint:disable-next-line: deprecation | ||
return new TaggedUnionType(name, U.is, U.validate, U.encode, codecs, tag); | ||
} | ||
return getTaggedUnion(indexRecord[tag], tag, codecs, name); | ||
}; | ||
@@ -1269,2 +1141,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
export var never = new NeverType(); | ||
@@ -1290,2 +1163,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
export var any = new AnyType(); | ||
@@ -1317,2 +1191,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
export var object = new ObjectType(); | ||
@@ -1340,2 +1215,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
export var Integer = refinement(number, Number.isInteger, 'Integer'); | ||
@@ -1354,3 +1230,9 @@ /** | ||
__extends(StrictType, _super); | ||
function StrictType(name, is, validate, encode, props) { | ||
function StrictType(name, | ||
// tslint:disable-next-line: deprecation | ||
is, | ||
// tslint:disable-next-line: deprecation | ||
validate, | ||
// tslint:disable-next-line: deprecation | ||
encode, props) { | ||
var _this = _super.call(this, name, is, validate, encode) || this; | ||
@@ -1375,1 +1257,151 @@ _this.props = props; | ||
} | ||
var isNonEmpty = function (as) { return as.length > 0; }; | ||
/** | ||
* @internal | ||
*/ | ||
export var emptyTags = {}; | ||
function intersect(a, b) { | ||
var r = []; | ||
for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { | ||
var v = a_1[_i]; | ||
if (b.indexOf(v) !== -1) { | ||
r.push(v); | ||
} | ||
} | ||
return r; | ||
} | ||
function mergeTags(a, b) { | ||
if (a === emptyTags) { | ||
return b; | ||
} | ||
if (b === emptyTags) { | ||
return a; | ||
} | ||
var r = Object.assign({}, a); | ||
for (var k in b) { | ||
if (a.hasOwnProperty(k)) { | ||
var intersection_1 = intersect(a[k], b[k]); | ||
if (isNonEmpty(intersection_1)) { | ||
r[k] = intersection_1; | ||
} | ||
else { | ||
r = emptyTags; | ||
break; | ||
} | ||
} | ||
else { | ||
r[k] = b[k]; | ||
} | ||
} | ||
return r; | ||
} | ||
function intersectTags(a, b) { | ||
if (a === emptyTags || b === emptyTags) { | ||
return emptyTags; | ||
} | ||
var r = emptyTags; | ||
for (var k in a) { | ||
if (b.hasOwnProperty(k)) { | ||
var intersection_2 = intersect(a[k], b[k]); | ||
if (intersection_2.length === 0) { | ||
if (r === emptyTags) { | ||
r = {}; | ||
} | ||
r[k] = a[k].concat(b[k]); | ||
} | ||
} | ||
} | ||
return r; | ||
} | ||
function isLiteralC(codec) { | ||
return codec._tag === 'LiteralType'; | ||
} | ||
function isTypeC(codec) { | ||
return codec._tag === 'InterfaceType'; | ||
} | ||
function isIntersectionC(codec) { | ||
return codec._tag === 'IntersectionType'; | ||
} | ||
function isUnionC(codec) { | ||
return codec._tag === 'UnionType'; | ||
} | ||
function isRecursiveC(codec) { | ||
return codec._tag === 'RecursiveType'; | ||
} | ||
var lazyCodec = null; | ||
/** | ||
* @internal | ||
*/ | ||
export function getTags(codec) { | ||
if (codec === lazyCodec) { | ||
return emptyTags; | ||
} | ||
if (isTypeC(codec)) { | ||
var index = emptyTags; | ||
// tslint:disable-next-line: forin | ||
for (var k in codec.props) { | ||
var prop = codec.props[k]; | ||
if (isLiteralC(prop)) { | ||
if (index === emptyTags) { | ||
index = {}; | ||
} | ||
index[k] = [prop.value]; | ||
} | ||
} | ||
return index; | ||
} | ||
else if (isIntersectionC(codec)) { | ||
return codec.types.reduce(function (tags, codec) { return mergeTags(tags, getTags(codec)); }, emptyTags); | ||
} | ||
else if (isUnionC(codec)) { | ||
return codec.types.slice(1).reduce(function (tags, codec) { return intersectTags(tags, getTags(codec)); }, getTags(codec.types[0])); | ||
} | ||
else if (isRecursiveC(codec)) { | ||
lazyCodec = codec; | ||
var tags = getTags(codec.type); | ||
lazyCodec = null; | ||
return tags; | ||
} | ||
return emptyTags; | ||
} | ||
/** | ||
* @internal | ||
*/ | ||
export function getIndex(codecs) { | ||
var tags = getTags(codecs[0]); | ||
var keys = Object.keys(tags); | ||
var len = codecs.length; | ||
var _loop_1 = function (k) { | ||
var all = tags[k].slice(); | ||
var index = [tags[k]]; | ||
for (var i = 1; i < len; i++) { | ||
var codec = codecs[i]; | ||
var ctags = getTags(codec); | ||
var values = ctags[k]; | ||
// tslint:disable-next-line: strict-type-predicates | ||
if (values === undefined) { | ||
return "continue-keys"; | ||
} | ||
else { | ||
if (values.some(function (v) { return all.indexOf(v) !== -1; })) { | ||
return "continue-keys"; | ||
} | ||
else { | ||
all.push.apply(all, values); | ||
index.push(values); | ||
} | ||
} | ||
} | ||
return { value: [k, index] }; | ||
}; | ||
keys: for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { | ||
var k = keys_1[_i]; | ||
var state_1 = _loop_1(k); | ||
if (typeof state_1 === "object") | ||
return state_1.value; | ||
switch (state_1) { | ||
case "continue-keys": continue keys; | ||
} | ||
} | ||
return undefined; | ||
} |
@@ -678,2 +678,3 @@ import { Either } from 'fp-ts/lib/Either'; | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
@@ -686,7 +687,12 @@ export declare class TaggedUnionType<Tag extends string, CS extends Array<Mixed>, A = any, O = A, I = unknown> extends UnionType<CS, A, O, I> { | ||
* @since 1.5.3 | ||
* @deprecated | ||
*/ | ||
export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Array<Mixed>]> extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> { | ||
export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Array<Mixed>]>// tslint:disable-next-line: deprecation | ||
extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> { | ||
} | ||
/** | ||
* Use `union` instead | ||
* | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
@@ -871,3 +877,4 @@ export declare const taggedUnion: <Tag extends string, CS extends [Mixed, Mixed, ...Mixed[]]>(tag: Tag, codecs: CS, name?: string) => TaggedUnionC<Tag, CS>; | ||
*/ | ||
export interface StrictC<P extends Props> extends StrictType<P, { | ||
export interface StrictC<P extends Props>// tslint:disable-next-line: deprecation | ||
extends StrictType<P, { | ||
[K in keyof P]: TypeOf<P[K]>; | ||
@@ -906,3 +913,4 @@ }, { | ||
*/ | ||
export interface TaggedIntersection<Tag extends string, A, O = A> extends IntersectionType<TaggedIntersectionArgument<Tag>, A, O> { | ||
export interface TaggedIntersection<Tag extends string, A, O = A>// tslint:disable-next-line: deprecation | ||
extends IntersectionType<TaggedIntersectionArgument<Tag>, A, O> { | ||
} | ||
@@ -909,0 +917,0 @@ /** |
486
lib/index.js
@@ -119,12 +119,6 @@ "use strict"; | ||
var isUnknownCodec = getIsCodec('UnknownType'); | ||
// tslint:disable-next-line: deprecation | ||
var isAnyCodec = getIsCodec('AnyType'); | ||
var isLiteralCodec = getIsCodec('LiteralType'); | ||
var isInterfaceCodec = getIsCodec('InterfaceType'); | ||
var isPartialCodec = getIsCodec('PartialType'); | ||
var isStrictCodec = getIsCodec('StrictType'); | ||
var isIntersectionCodec = getIsCodec('IntersectionType'); | ||
var isUnionCodec = getIsCodec('UnionType'); | ||
var isExactCodec = getIsCodec('ExactType'); | ||
var isRefinementCodec = getIsCodec('RefinementType'); | ||
var isRecursiveCodec = getIsCodec('RecursiveType'); | ||
// | ||
@@ -309,2 +303,3 @@ // basic types | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
exports.Function = new FunctionType(); | ||
@@ -330,2 +325,3 @@ /** | ||
exports.brand = function (codec, predicate, name) { | ||
// tslint:disable-next-line: deprecation | ||
return refinement(codec, predicate, name); | ||
@@ -419,11 +415,2 @@ }; | ||
var Self = new RecursiveType(name, function (u) { return runDefinition().is(u); }, function (u, c) { return runDefinition().validate(u, c); }, function (a) { return runDefinition().encode(a); }, runDefinition); | ||
var indexRecordCache; | ||
Self.getIndexRecord = function () { | ||
if (!indexRecordCache) { | ||
isRecursiveCodecIndexable = false; | ||
indexRecordCache = getCodecIndexRecord(definition(Self), Self, Self); | ||
isRecursiveCodecIndexable = true; | ||
} | ||
return indexRecordCache; | ||
}; | ||
return Self; | ||
@@ -497,4 +484,4 @@ }; | ||
}; | ||
var useIdentity = function (codecs, len) { | ||
for (var i = 0; i < len; i++) { | ||
var useIdentity = function (codecs) { | ||
for (var i = 0; i < codecs.length; i++) { | ||
if (codecs[i].encode !== exports.identity) { | ||
@@ -563,3 +550,3 @@ return false; | ||
return errors.length > 0 ? exports.failures(errors) : exports.success(a); | ||
}, useIdentity(types, len) | ||
}, useIdentity(types) | ||
? exports.identity | ||
@@ -644,3 +631,3 @@ : function (a) { | ||
return errors.length > 0 ? exports.failures(errors) : exports.success(a); | ||
}, useIdentity(types, len) | ||
}, useIdentity(types) | ||
? exports.identity | ||
@@ -760,26 +747,71 @@ : function (a) { | ||
if (name === void 0) { name = getUnionName(codecs); } | ||
var len = codecs.length; | ||
return new UnionType(name, function (u) { return codecs.some(function (type) { return type.is(u); }); }, function (u, c) { | ||
var errors = []; | ||
for (var i = 0; i < len; i++) { | ||
var type_3 = codecs[i]; | ||
var validation = type_3.validate(u, exports.appendContext(c, String(i), type_3, u)); | ||
if (validation.isRight()) { | ||
return validation; | ||
var index = getIndex(codecs); | ||
if (index !== undefined && codecs.length > 0) { | ||
var tag_1 = index[0], groups_1 = index[1]; | ||
var len_1 = groups_1.length; | ||
var find_1 = function (value) { | ||
for (var i = 0; i < len_1; i++) { | ||
if (groups_1[i].indexOf(value) !== -1) { | ||
return i; | ||
} | ||
} | ||
pushAll(errors, validation.value); | ||
} | ||
return errors.length > 0 ? exports.failures(errors) : exports.failure(u, c); | ||
}, useIdentity(codecs, len) | ||
? exports.identity | ||
: function (a) { | ||
for (var i = 0; i < len; i++) { | ||
return undefined; | ||
}; | ||
// tslint:disable-next-line: deprecation | ||
return new TaggedUnionType(name, function (u) { | ||
if (!exports.UnknownRecord.is(u)) { | ||
return false; | ||
} | ||
var i = find_1(u[tag_1]); | ||
return i !== undefined ? codecs[i].is(u) : false; | ||
}, function (u, c) { | ||
var dictionaryResult = exports.UnknownRecord.validate(u, c); | ||
if (dictionaryResult.isLeft()) { | ||
return dictionaryResult; | ||
} | ||
var r = dictionaryResult.value; | ||
var i = find_1(r[tag_1]); | ||
if (i === undefined) { | ||
return exports.failure(u, c); | ||
} | ||
var codec = codecs[i]; | ||
return codec.validate(r, exports.appendContext(c, String(i), codec, r)); | ||
}, useIdentity(codecs) | ||
? exports.identity | ||
: function (a) { | ||
var i = find_1(a[tag_1]); | ||
if (i === undefined) { | ||
// https://github.com/gcanti/io-ts/pull/305 | ||
throw new Error("no codec found to encode value in union codec " + name); | ||
} | ||
else { | ||
return codecs[i].encode(a); | ||
} | ||
}, codecs, tag_1); | ||
} | ||
else { | ||
return new UnionType(name, function (u) { return codecs.some(function (type) { return type.is(u); }); }, function (u, c) { | ||
var errors = []; | ||
for (var i = 0; i < codecs.length; i++) { | ||
var codec = codecs[i]; | ||
if (codec.is(a)) { | ||
return codec.encode(a); | ||
var validation = codec.validate(u, exports.appendContext(c, String(i), codec, u)); | ||
if (validation.isRight()) { | ||
return validation; | ||
} | ||
pushAll(errors, validation.value); | ||
} | ||
// https://github.com/gcanti/io-ts/pull/305 | ||
throw new Error("no codec found to encode value in union type " + name); | ||
}, codecs); | ||
return exports.failures(errors); | ||
}, useIdentity(codecs) | ||
? exports.identity | ||
: function (a) { | ||
for (var _i = 0, codecs_1 = codecs; _i < codecs_1.length; _i++) { | ||
var codec = codecs_1[_i]; | ||
if (codec.is(a)) { | ||
return codec.encode(a); | ||
} | ||
} | ||
// https://github.com/gcanti/io-ts/pull/305 | ||
throw new Error("no codec found to encode value in union type " + name); | ||
}, codecs); | ||
} | ||
}; | ||
@@ -868,4 +900,4 @@ /** | ||
var a = us[i]; | ||
var type_4 = codecs[i]; | ||
var validation = type_4.validate(a, exports.appendContext(c, String(i), type_4, a)); | ||
var type_3 = codecs[i]; | ||
var validation = type_3.validate(a, exports.appendContext(c, String(i), type_3, a)); | ||
if (validation.isLeft()) { | ||
@@ -886,3 +918,3 @@ pushAll(errors, validation.value); | ||
return errors.length > 0 ? exports.failures(errors) : exports.success(as); | ||
}, useIdentity(codecs, len) ? exports.identity : function (a) { return codecs.map(function (type, i) { return type.encode(a[i]); }); }, codecs); | ||
}, useIdentity(codecs) ? exports.identity : function (a) { return codecs.map(function (type, i) { return type.encode(a[i]); }); }, codecs); | ||
} | ||
@@ -954,181 +986,15 @@ exports.tuple = tuple; | ||
}; | ||
/** @internal */ | ||
exports.emptyIndexRecord = {}; | ||
var monoidIndexRecord = { | ||
concat: function (a, b) { | ||
var _a; | ||
if (a === monoidIndexRecord.empty) { | ||
return b; | ||
} | ||
if (b === monoidIndexRecord.empty) { | ||
return a; | ||
} | ||
var r = cloneIndexRecord(a); | ||
for (var k in b) { | ||
if (r.hasOwnProperty(k)) { | ||
(_a = r[k]).push.apply(_a, b[k]); | ||
} | ||
else { | ||
r[k] = b[k]; | ||
} | ||
} | ||
return r; | ||
}, | ||
empty: exports.emptyIndexRecord | ||
}; | ||
var isIndexRecordEmpty = function (a) { | ||
for (var _ in a) { | ||
return false; | ||
} | ||
return true; | ||
}; | ||
var foldMapIndexRecord = function (as, f) { | ||
return as.reduce(function (acc, a) { return monoidIndexRecord.concat(acc, f(a)); }, monoidIndexRecord.empty); | ||
}; | ||
var cloneIndexRecord = function (a) { | ||
var r = {}; | ||
for (var k in a) { | ||
r[k] = a[k].slice(); | ||
} | ||
return r; | ||
}; | ||
var updateindexRecordOrigin = function (origin, indexRecord) { | ||
var r = {}; | ||
for (var k in indexRecord) { | ||
r[k] = indexRecord[k].map(function (_a) { | ||
var v = _a[0], _ = _a[1], id = _a[2]; | ||
return [v, origin, id]; | ||
}); | ||
} | ||
return r; | ||
}; | ||
var getCodecIndexRecord = function (codec, origin, id) { | ||
if (isInterfaceCodec(codec) || isStrictCodec(codec)) { | ||
var interfaceIndex = {}; | ||
for (var k in codec.props) { | ||
var prop = codec.props[k]; | ||
if (isLiteralCodec(prop)) { | ||
var value = prop.value; | ||
interfaceIndex[k] = [[value, origin, id]]; | ||
} | ||
} | ||
return interfaceIndex; | ||
} | ||
if (isIntersectionCodec(codec)) { | ||
return foldMapIndexRecord(codec.types, function (type) { return getCodecIndexRecord(type, origin, codec); }); | ||
} | ||
if (isUnionCodec(codec)) { | ||
return foldMapIndexRecord(codec.types, function (type) { return getCodecIndexRecord(type, origin, type); }); | ||
} | ||
if (isExactCodec(codec) || isRefinementCodec(codec)) { | ||
return getCodecIndexRecord(codec.type, origin, codec); | ||
} | ||
if (isRecursiveCodec(codec)) { | ||
var indexRecord = codec.getIndexRecord(); | ||
if (codec !== origin) { | ||
return updateindexRecordOrigin(origin, indexRecord); | ||
} | ||
return indexRecord; | ||
} | ||
return monoidIndexRecord.empty; | ||
}; | ||
var isRecursiveCodecIndexable = true; | ||
var isIndexableCodec = function (codec) { | ||
return (((isInterfaceCodec(codec) || isStrictCodec(codec)) && | ||
Object.keys(codec.props).some(function (key) { return isLiteralCodec(codec.props[key]); })) || | ||
((isExactCodec(codec) || isRefinementCodec(codec)) && isIndexableCodec(codec.type)) || | ||
(isIntersectionCodec(codec) && codec.types.some(isIndexableCodec)) || | ||
(isUnionCodec(codec) && codec.types.every(isIndexableCodec)) || | ||
(isRecursiveCodecIndexable && isRecursiveCodec(codec))); | ||
}; | ||
/** | ||
* @internal | ||
*/ | ||
exports.getIndexRecord = function (codecs) { | ||
var len = codecs.length; | ||
if (len === 0 || !codecs.every(isIndexableCodec)) { | ||
return monoidIndexRecord.empty; | ||
} | ||
var firstCodec = codecs[0]; | ||
var ir = cloneIndexRecord(getCodecIndexRecord(firstCodec, firstCodec, firstCodec)); | ||
for (var i = 1; i < len; i++) { | ||
var codec = codecs[i]; | ||
var cir = getCodecIndexRecord(codec, codec, codec); | ||
for (var k in ir) { | ||
if (cir.hasOwnProperty(k)) { | ||
var is = ir[k]; | ||
var cis = cir[k]; | ||
var _loop_1 = function (j) { | ||
var indexItem = cis[j]; | ||
var index = is.findIndex(function (_a) { | ||
var v = _a[0]; | ||
return v === indexItem[0]; | ||
}); | ||
if (index === -1) { | ||
is.push(indexItem); | ||
} | ||
else if (indexItem[2] !== is[index][2]) { | ||
delete ir[k]; | ||
return "break"; | ||
} | ||
}; | ||
for (var j = 0; j < cis.length; j++) { | ||
var state_1 = _loop_1(j); | ||
if (state_1 === "break") | ||
break; | ||
} | ||
} | ||
else { | ||
delete ir[k]; | ||
} | ||
} | ||
} | ||
return isIndexRecordEmpty(ir) ? monoidIndexRecord.empty : ir; | ||
}; | ||
var getTaggedUnion = function (index, tag, codecs, name) { | ||
var len = codecs.length; | ||
var indexWithPosition = index.map(function (_a) { | ||
var v = _a[0], origin = _a[1]; | ||
return [ | ||
v, | ||
codecs.findIndex(function (codec) { return codec === origin; }) | ||
]; | ||
}); | ||
var findIndex = function (tagValue) { | ||
for (var i = 0; i < indexWithPosition.length; i++) { | ||
var _a = indexWithPosition[i], value = _a[0], position = _a[1]; | ||
if (value === tagValue) { | ||
return position; | ||
} | ||
} | ||
}; | ||
var isTagValue = function (u) { return findIndex(u) !== undefined; }; | ||
return new TaggedUnionType(name, function (u) { | ||
if (!exports.UnknownRecord.is(u)) { | ||
return false; | ||
} | ||
var tagValue = u[tag]; | ||
var index = findIndex(tagValue); | ||
return index !== undefined ? codecs[index].is(u) : false; | ||
}, function (u, c) { | ||
var dictionaryResult = exports.UnknownRecord.validate(u, c); | ||
if (dictionaryResult.isLeft()) { | ||
return dictionaryResult; | ||
} | ||
var d = dictionaryResult.value; | ||
var tagValue = d[tag]; | ||
if (!isTagValue(tagValue)) { | ||
return exports.failure(u, c); | ||
} | ||
var index = findIndex(tagValue); | ||
var codec = codecs[index]; | ||
return codec.validate(d, exports.appendContext(c, String(index), codec, d)); | ||
}, useIdentity(codecs, len) ? exports.identity : function (a) { return codecs[findIndex(a[tag])].encode(a); }, codecs, tag); | ||
}; | ||
/** | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
var TaggedUnionType = /** @class */ (function (_super) { | ||
__extends(TaggedUnionType, _super); | ||
function TaggedUnionType(name, is, validate, encode, codecs, tag) { | ||
function TaggedUnionType(name, | ||
// tslint:disable-next-line: deprecation | ||
is, | ||
// tslint:disable-next-line: deprecation | ||
validate, | ||
// tslint:disable-next-line: deprecation | ||
encode, codecs, tag) { | ||
var _this = _super.call(this, name, is, validate, encode, codecs) /* istanbul ignore next */ // <= workaround for https://github.com/Microsoft/TypeScript/issues/13455 | ||
@@ -1143,15 +1009,21 @@ || this; | ||
/** | ||
* Use `union` instead | ||
* | ||
* @since 1.3.0 | ||
* @deprecated | ||
*/ | ||
exports.taggedUnion = function (tag, codecs, name) { | ||
exports.taggedUnion = function (tag, codecs, name | ||
// tslint:disable-next-line: deprecation | ||
) { | ||
if (name === void 0) { name = getUnionName(codecs); } | ||
var indexRecord = exports.getIndexRecord(codecs); | ||
if (!indexRecord.hasOwnProperty(tag)) { | ||
if (isRecursiveCodecIndexable && codecs.length > 0) { | ||
console.warn("[io-ts] Cannot build a tagged union for " + name + ", returning a de-optimized union"); | ||
} | ||
var U = exports.union(codecs, name); | ||
var U = exports.union(codecs, name); | ||
// tslint:disable-next-line: deprecation | ||
if (U instanceof TaggedUnionType) { | ||
return U; | ||
} | ||
else { | ||
console.warn("[io-ts] Cannot build a tagged union for " + name + ", returning a de-optimized union"); | ||
// tslint:disable-next-line: deprecation | ||
return new TaggedUnionType(name, U.is, U.validate, U.encode, codecs, tag); | ||
} | ||
return getTaggedUnion(indexRecord[tag], tag, codecs, name); | ||
}; | ||
@@ -1265,2 +1137,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
exports.never = new NeverType(); | ||
@@ -1286,2 +1159,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
exports.any = new AnyType(); | ||
@@ -1313,2 +1187,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
exports.object = new ObjectType(); | ||
@@ -1337,2 +1212,3 @@ /** | ||
*/ | ||
// tslint:disable-next-line: deprecation | ||
exports.Integer = refinement(exports.number, Number.isInteger, 'Integer'); | ||
@@ -1351,3 +1227,9 @@ /** | ||
__extends(StrictType, _super); | ||
function StrictType(name, is, validate, encode, props) { | ||
function StrictType(name, | ||
// tslint:disable-next-line: deprecation | ||
is, | ||
// tslint:disable-next-line: deprecation | ||
validate, | ||
// tslint:disable-next-line: deprecation | ||
encode, props) { | ||
var _this = _super.call(this, name, is, validate, encode) || this; | ||
@@ -1374,1 +1256,153 @@ _this.props = props; | ||
exports.alias = alias; | ||
var isNonEmpty = function (as) { return as.length > 0; }; | ||
/** | ||
* @internal | ||
*/ | ||
exports.emptyTags = {}; | ||
function intersect(a, b) { | ||
var r = []; | ||
for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { | ||
var v = a_1[_i]; | ||
if (b.indexOf(v) !== -1) { | ||
r.push(v); | ||
} | ||
} | ||
return r; | ||
} | ||
function mergeTags(a, b) { | ||
if (a === exports.emptyTags) { | ||
return b; | ||
} | ||
if (b === exports.emptyTags) { | ||
return a; | ||
} | ||
var r = Object.assign({}, a); | ||
for (var k in b) { | ||
if (a.hasOwnProperty(k)) { | ||
var intersection_1 = intersect(a[k], b[k]); | ||
if (isNonEmpty(intersection_1)) { | ||
r[k] = intersection_1; | ||
} | ||
else { | ||
r = exports.emptyTags; | ||
break; | ||
} | ||
} | ||
else { | ||
r[k] = b[k]; | ||
} | ||
} | ||
return r; | ||
} | ||
function intersectTags(a, b) { | ||
if (a === exports.emptyTags || b === exports.emptyTags) { | ||
return exports.emptyTags; | ||
} | ||
var r = exports.emptyTags; | ||
for (var k in a) { | ||
if (b.hasOwnProperty(k)) { | ||
var intersection_2 = intersect(a[k], b[k]); | ||
if (intersection_2.length === 0) { | ||
if (r === exports.emptyTags) { | ||
r = {}; | ||
} | ||
r[k] = a[k].concat(b[k]); | ||
} | ||
} | ||
} | ||
return r; | ||
} | ||
function isLiteralC(codec) { | ||
return codec._tag === 'LiteralType'; | ||
} | ||
function isTypeC(codec) { | ||
return codec._tag === 'InterfaceType'; | ||
} | ||
function isIntersectionC(codec) { | ||
return codec._tag === 'IntersectionType'; | ||
} | ||
function isUnionC(codec) { | ||
return codec._tag === 'UnionType'; | ||
} | ||
function isRecursiveC(codec) { | ||
return codec._tag === 'RecursiveType'; | ||
} | ||
var lazyCodec = null; | ||
/** | ||
* @internal | ||
*/ | ||
function getTags(codec) { | ||
if (codec === lazyCodec) { | ||
return exports.emptyTags; | ||
} | ||
if (isTypeC(codec)) { | ||
var index = exports.emptyTags; | ||
// tslint:disable-next-line: forin | ||
for (var k in codec.props) { | ||
var prop = codec.props[k]; | ||
if (isLiteralC(prop)) { | ||
if (index === exports.emptyTags) { | ||
index = {}; | ||
} | ||
index[k] = [prop.value]; | ||
} | ||
} | ||
return index; | ||
} | ||
else if (isIntersectionC(codec)) { | ||
return codec.types.reduce(function (tags, codec) { return mergeTags(tags, getTags(codec)); }, exports.emptyTags); | ||
} | ||
else if (isUnionC(codec)) { | ||
return codec.types.slice(1).reduce(function (tags, codec) { return intersectTags(tags, getTags(codec)); }, getTags(codec.types[0])); | ||
} | ||
else if (isRecursiveC(codec)) { | ||
lazyCodec = codec; | ||
var tags = getTags(codec.type); | ||
lazyCodec = null; | ||
return tags; | ||
} | ||
return exports.emptyTags; | ||
} | ||
exports.getTags = getTags; | ||
/** | ||
* @internal | ||
*/ | ||
function getIndex(codecs) { | ||
var tags = getTags(codecs[0]); | ||
var keys = Object.keys(tags); | ||
var len = codecs.length; | ||
var _loop_1 = function (k) { | ||
var all = tags[k].slice(); | ||
var index = [tags[k]]; | ||
for (var i = 1; i < len; i++) { | ||
var codec = codecs[i]; | ||
var ctags = getTags(codec); | ||
var values = ctags[k]; | ||
// tslint:disable-next-line: strict-type-predicates | ||
if (values === undefined) { | ||
return "continue-keys"; | ||
} | ||
else { | ||
if (values.some(function (v) { return all.indexOf(v) !== -1; })) { | ||
return "continue-keys"; | ||
} | ||
else { | ||
all.push.apply(all, values); | ||
index.push(values); | ||
} | ||
} | ||
} | ||
return { value: [k, index] }; | ||
}; | ||
keys: for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { | ||
var k = keys_1[_i]; | ||
var state_1 = _loop_1(k); | ||
if (typeof state_1 === "object") | ||
return state_1.value; | ||
switch (state_1) { | ||
case "continue-keys": continue keys; | ||
} | ||
} | ||
return undefined; | ||
} | ||
exports.getIndex = getIndex; |
{ | ||
"name": "io-ts", | ||
"version": "1.8.6", | ||
"version": "1.9.0", | ||
"description": "TypeScript compatible runtime type system for IO validation", | ||
@@ -14,7 +14,7 @@ "files": [ | ||
"scripts": { | ||
"lint": "tslint -p tsconfig.json src/**/*.ts test/**/*.ts", | ||
"lint": "tslint -p tsconfig.tslint.json src/**/*.ts test/**/*.ts", | ||
"jest": "jest", | ||
"prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test}/**/*.ts\"", | ||
"fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,test,examples,exercises}/**/*.ts\"", | ||
"test": "npm run prettier && npm run lint && npm run dtslint && npm run declaration && npm run jest", | ||
"test": "npm run prettier && npm run lint && npm run dtslint && npm run declaration && npm run jest && npm run docs", | ||
"clean": "rimraf lib/* es6/*", | ||
@@ -48,3 +48,3 @@ "build": "npm run clean && tsc && tsc -p tsconfig.es6.json", | ||
"benchmark": "2.1.4", | ||
"docs-ts": "0.0.1", | ||
"docs-ts": "0.0.3", | ||
"doctoc": "^1.4.0", | ||
@@ -51,0 +51,0 @@ "dtslint": "github:gcanti/dtslint", |
@@ -20,3 +20,2 @@ [![build status](https://img.shields.io/travis/gcanti/io-ts/master.svg?style=flat-square)](https://travis-ci.org/gcanti/io-ts) | ||
- [Mutually recursive types](#mutually-recursive-types) | ||
- [Tagged unions](#tagged-unions) | ||
- [Branded types / Refinements](#branded-types--refinements) | ||
@@ -254,3 +253,3 @@ - [Exact types](#exact-types) | ||
| tuple | `[ A, B ]` | `t.tuple([ A, B ])` | | ||
| union | `A \| B` | `t.union([ A, B ])` or `t.taggedUnion(tag, [ A, B ])` | | ||
| union | `A \| B` | `t.union([ A, B ])` | | ||
| intersection | `A & B` | `t.intersection([ A, B ])` | | ||
@@ -310,22 +309,2 @@ | keyof | `keyof M` | `t.keyof(M)` (**only supports string keys**) | | ||
# 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]) | ||
``` | ||
# Branded types / Refinements | ||
@@ -332,0 +311,0 @@ |
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
4871
180263
556