Socket
Socket
Sign inDemoInstall

io-ts

Package Overview
Dependencies
Maintainers
1
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

io-ts - npm Package Compare versions

Comparing version 1.7.1 to 1.8.0

28

CHANGELOG.md

@@ -17,2 +17,30 @@ # Changelog

# 1.8.0
- **New Feature**
- add `brand` combinator (@gcanti)
- add `Int` codec (@gcanti)
- `exact` strips additional properties while decoding / encoding (@gcanti)
- un-deprecate `strict` combinator, is now an alias of `exact(type(...))` (@gcanti)
- **Bug Fix**
- fix wrong context keys for tagged unions (@gcanti)
- **Deprecation**
- deprecate `refinement` combinator in favour of `brand` (@gcanti)
- deprecate `Integer` codec in favour of `Int` (@gcanti)
- deprecate `StrictType` class (@gcanti)
- deprecate `StrictC` interface (@gcanti)
- **Polish**
- modify the implementation of `intersection` in order to support combinators that strip additional properties (@gcanti)
- do not validate the codomain of a key of a record if its domain in invalid (@gcanti)
- normalize missing `message` field in `ValidationError` (@gcanti)
- fix name of recursive codec definitions (@gcanti)
- remove unexpected validation path from partial type, closes #195 (@gcanti)
- do not leak taggedUnion implementation when tag validation fails (@gcanti)
- add `actual` value to all context entries (@gcanti)
- `exact` now bails out when the value is not an `UnknownRecord` (@gcanti)
- `tuple` should not leak the implementation (`never` usage) (@gcanti)
- `exact` should not leak the implementation (`never` usage) (@gcanti)
- use `Number.isInteger` in `Integer` implementation (@gcanti)
- use the Flow convention to name `exact` codecs (@gcanti)
# 1.7.1

@@ -19,0 +47,0 @@

38

lib/index.d.ts

@@ -148,3 +148,3 @@ import { Either } from 'fp-ts/lib/Either';

*/
export declare const appendContext: (c: Context, key: string, decoder: Decoder<any, any>) => Context;
export declare const appendContext: (c: Context, key: string, decoder: Decoder<any, any>, actual?: unknown) => Context;
/**

@@ -391,3 +391,5 @@ * @since 1.0.0

/**
* Use `BrandC` instead
* @since 1.5.3
* @deprecated
*/

@@ -397,9 +399,33 @@ export interface RefinementC<C extends Any> extends RefinementType<C, TypeOf<C>, OutputOf<C>, InputOf<C>> {

/**
* Use `brand` instead
* @since 1.0.0
* @deprecated
*/
export declare const refinement: <C extends Any>(codec: C, predicate: Predicate<C["_A"]>, name?: string) => RefinementC<C>;
/**
* Use `Int` instead
* @since 1.0.0
* @deprecated
*/
export declare const Integer: RefinementC<NumberC>;
declare const _brand: unique symbol;
/**
* @since 1.8.0
*/
export interface Brand<B> {
readonly [_brand]: B;
}
/**
* @since 1.8.0
*/
export interface BrandC<C extends Any, B> extends RefinementType<C, TypeOf<C> & Brand<B>, OutputOf<C>, InputOf<C>> {
}
/**
* @since 1.8.0
*/
export declare const brand: <C extends Any, B extends string>(codec: C, predicate: Predicate<C["_A"]>, name: B) => BrandC<C, B>;
/**
* @since 1.8.0
*/
export declare const Int: BrandC<NumberC, "Int">;
declare type LiteralValue = string | number | boolean;

@@ -703,2 +729,3 @@ /**

* @since 1.0.0
* @deprecated
*/

@@ -712,2 +739,3 @@ export declare class StrictType<P, A = any, O = A, I = unknown> extends Type<A, O, I> {

* @since 1.5.3
* @deprecated
*/

@@ -721,7 +749,6 @@ export interface StrictC<P extends Props> extends StrictType<P, {

/**
* Specifies that only the given properties are allowed
* @deprecated use `exact` instead
* Strips additional properties
* @since 1.0.0
*/
export declare const strict: <P extends Props>(props: P, name?: string) => StrictC<P>;
export declare const strict: <P extends Props>(props: P, name?: string | undefined) => ExactC<TypeC<P>>;
/**

@@ -821,5 +848,6 @@ * @since 1.3.0

/**
* Strips additional properties
* @since 1.1.0
*/
export declare function exact<C extends HasProps>(codec: C, name?: string): ExactC<C>;
export declare const exact: <C extends HasProps>(codec: C, name?: string) => ExactC<C>;
/**

@@ -826,0 +854,0 @@ * Drops the codec "kind"

488

lib/index.js

@@ -54,5 +54,3 @@ "use strict";

}
else {
return ab.validate(validation.value, c);
}
return ab.validate(validation.value, c);
}, this.encode === exports.identity && ab.encode === exports.identity ? exports.identity : function (b) { return _this.encode(ab.encode(b)); });

@@ -105,3 +103,3 @@ };

*/
exports.appendContext = function (c, key, decoder) {
exports.appendContext = function (c, key, decoder, actual) {
var len = c.length;

@@ -112,3 +110,3 @@ var r = Array(len + 1);

}
r[len] = { key: key, type: decoder };
r[len] = { key: key, type: decoder, actual: actual };
return r;

@@ -141,2 +139,3 @@ };

var isInterfaceCodec = getIsCodec('InterfaceType');
var isPartialCodec = getIsCodec('PartialType');
var isStrictCodec = getIsCodec('StrictType');

@@ -407,3 +406,5 @@ var isIntersectionCodec = getIsCodec('IntersectionType');

/**
* Use `brand` instead
* @since 1.0.0
* @deprecated
*/

@@ -417,13 +418,23 @@ exports.refinement = function (codec, predicate, name) {

}
else {
var a = validation.value;
return predicate(a) ? exports.success(a) : exports.failure(a, c);
}
var a = validation.value;
return predicate(a) ? exports.success(a) : exports.failure(a, c);
}, codec.encode, codec, predicate);
};
/**
* Use `Int` instead
* @since 1.0.0
* @deprecated
*/
exports.Integer = exports.refinement(exports.number, function (n) { return n % 1 === 0; }, 'Integer');
exports.Integer = exports.refinement(exports.number, Number.isInteger, 'Integer');
/**
* @since 1.8.0
*/
exports.brand = function (codec, predicate, name) {
return exports.refinement(codec, predicate, name);
};
/**
* @since 1.8.0
*/
exports.Int = exports.brand(exports.number, Number.isInteger, 'Int');
/**
* @since 1.0.0

@@ -504,2 +515,3 @@ */

cache = definition(Self);
cache.name = name;
}

@@ -540,29 +552,27 @@ return cache;

return new ArrayType(name, function (u) { return exports.UnknownArray.is(u) && u.every(codec.is); }, function (u, c) {
var arrayValidation = exports.UnknownArray.validate(u, c);
if (arrayValidation.isLeft()) {
return arrayValidation;
var unknownArrayValidation = exports.UnknownArray.validate(u, c);
if (unknownArrayValidation.isLeft()) {
return unknownArrayValidation;
}
else {
var xs = arrayValidation.value;
var len = xs.length;
var a = xs;
var errors = [];
for (var i = 0; i < len; i++) {
var x = xs[i];
var validation = codec.validate(x, exports.appendContext(c, String(i), codec));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var vx = validation.value;
if (vx !== x) {
if (a === xs) {
a = xs.slice();
}
a[i] = vx;
var us = unknownArrayValidation.value;
var len = us.length;
var as = us;
var errors = [];
for (var i = 0; i < len; i++) {
var ui = us[i];
var validation = codec.validate(ui, exports.appendContext(c, String(i), codec, ui));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var ai = validation.value;
if (ai !== ui) {
if (as === us) {
as = us.slice();
}
as[i] = ai;
}
}
return errors.length ? exports.failures(errors) : exports.success(a);
}
return errors.length > 0 ? exports.failures(errors) : exports.success(as);
}, codec.encode === exports.identity ? exports.identity : function (a) { return a.map(codec.encode); }, codec);

@@ -585,5 +595,5 @@ };

var getNameFromProps = function (props) {
return "{ " + Object.keys(props)
return Object.keys(props)
.map(function (k) { return k + ": " + props[k].name; })
.join(', ') + " }";
.join(', ');
};

@@ -598,2 +608,5 @@ var useIdentity = function (codecs, len) {

};
var getInterfaceTypeName = function (props) {
return "{ " + getNameFromProps(props) + " }";
};
/**

@@ -604,3 +617,3 @@ * @alias `interface`

exports.type = function (props, name) {
if (name === void 0) { name = getNameFromProps(props); }
if (name === void 0) { name = getInterfaceTypeName(props); }
var keys = Object.keys(props);

@@ -621,37 +634,35 @@ var types = keys.map(function (key) { return props[key]; });

}, function (u, c) {
var dictionaryValidation = exports.UnknownRecord.validate(u, c);
if (dictionaryValidation.isLeft()) {
return dictionaryValidation;
var unknownRecordValidation = exports.UnknownRecord.validate(u, c);
if (unknownRecordValidation.isLeft()) {
return unknownRecordValidation;
}
else {
var o = dictionaryValidation.value;
var a = o;
var errors = [];
for (var i = 0; i < len; i++) {
var k = keys[i];
if (!hasOwnProperty.call(a, k)) {
var o = unknownRecordValidation.value;
var a = o;
var errors = [];
for (var i = 0; i < len; i++) {
var k = keys[i];
if (!hasOwnProperty.call(a, k)) {
if (a === o) {
a = __assign({}, o);
}
a[k] = a[k];
}
var ak = a[k];
var type_1 = types[i];
var validation = type_1.validate(ak, exports.appendContext(c, k, type_1, ak));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var vak = validation.value;
if (vak !== ak) {
/* istanbul ignore next */
if (a === o) {
a = __assign({}, o);
}
a[k] = a[k];
a[k] = vak;
}
var ak = a[k];
var type_1 = types[i];
var validation = type_1.validate(ak, exports.appendContext(c, k, type_1));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var vak = validation.value;
if (vak !== ak) {
/* istanbul ignore next */
if (a === o) {
a = __assign({}, o);
}
a[k] = vak;
}
}
}
return errors.length ? exports.failures(errors) : exports.success(a);
}
return errors.length > 0 ? exports.failures(errors) : exports.success(a);
}, useIdentity(types, len)

@@ -686,2 +697,5 @@ ? exports.identity

exports.PartialType = PartialType;
var getPartialTypeName = function (inner) {
return "Partial<" + inner + ">";
};
/**

@@ -691,10 +705,6 @@ * @since 1.0.0

exports.partial = function (props, name) {
if (name === void 0) { name = "Partial<" + getNameFromProps(props) + ">"; }
if (name === void 0) { name = getPartialTypeName(getInterfaceTypeName(props)); }
var keys = Object.keys(props);
var types = keys.map(function (key) { return props[key]; });
var len = keys.length;
var partials = {};
for (var i = 0; i < len; i++) {
partials[keys[i]] = exports.union([types[i], undefinedType]);
}
return new PartialType(name, function (u) {

@@ -706,3 +716,4 @@ if (!exports.UnknownRecord.is(u)) {

var k = keys[i];
if (!partials[k].is(u[k])) {
var uk = u[k];
if (uk !== undefined && !props[k].is(uk)) {
return false;

@@ -713,31 +724,29 @@ }

}, function (u, c) {
var dictionaryValidation = exports.UnknownRecord.validate(u, c);
if (dictionaryValidation.isLeft()) {
return dictionaryValidation;
var unknownRecordValidation = exports.UnknownRecord.validate(u, c);
if (unknownRecordValidation.isLeft()) {
return unknownRecordValidation;
}
else {
var o = dictionaryValidation.value;
var a = o;
var errors = [];
for (var i = 0; i < len; i++) {
var k = keys[i];
var ak = a[k];
var type_2 = partials[k];
var validation = type_2.validate(ak, exports.appendContext(c, k, type_2));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var vak = validation.value;
if (vak !== ak) {
/* istanbul ignore next */
if (a === o) {
a = __assign({}, o);
}
a[k] = vak;
var o = unknownRecordValidation.value;
var a = o;
var errors = [];
for (var i = 0; i < len; i++) {
var k = keys[i];
var ak = a[k];
var type_2 = props[k];
var validation = type_2.validate(ak, exports.appendContext(c, k, type_2, ak));
if (validation.isLeft() && ak !== undefined) {
pushAll(errors, validation.value);
}
else if (validation.isRight()) {
var vak = validation.value;
if (vak !== ak) {
/* istanbul ignore next */
if (a === o) {
a = __assign({}, o);
}
a[k] = vak;
}
}
return errors.length ? exports.failures(errors) : exports.success(a);
}
return errors.length > 0 ? exports.failures(errors) : exports.success(a);
}, useIdentity(types, len)

@@ -787,29 +796,27 @@ ? exports.identity

}, function (u, c) {
var dictionaryValidation = exports.UnknownRecord.validate(u, c);
if (dictionaryValidation.isLeft()) {
return dictionaryValidation;
var unknownRecordValidation = exports.UnknownRecord.validate(u, c);
if (unknownRecordValidation.isLeft()) {
return unknownRecordValidation;
}
else {
var o = dictionaryValidation.value;
if (!isUnknownCodec(codomain) && !isAnyCodec(codomain) && !isObject(o)) {
return exports.failure(u, c);
var o = unknownRecordValidation.value;
if (!isUnknownCodec(codomain) && !isAnyCodec(codomain) && !isObject(o)) {
return exports.failure(u, c);
}
var a = {};
var errors = [];
var keys = Object.keys(o);
var len = keys.length;
var changed = false;
for (var i = 0; i < len; i++) {
var k = keys[i];
var ok = o[k];
var domainValidation = domain.validate(k, exports.appendContext(c, k, domain, k));
if (domainValidation.isLeft()) {
pushAll(errors, domainValidation.value);
}
var a = {};
var errors = [];
var keys = Object.keys(o);
var len = keys.length;
var changed = false;
for (var i = 0; i < len; i++) {
var k = keys[i];
var ok = o[k];
var domainValidation = domain.validate(k, exports.appendContext(c, k, domain));
var codomainValidation = codomain.validate(ok, exports.appendContext(c, k, codomain));
if (domainValidation.isLeft()) {
pushAll(errors, domainValidation.value);
}
else {
var vk = domainValidation.value;
changed = changed || vk !== k;
k = vk;
}
else {
var vk = domainValidation.value;
changed = changed || vk !== k;
k = vk;
var codomainValidation = codomain.validate(ok, exports.appendContext(c, k, codomain, ok));
if (codomainValidation.isLeft()) {

@@ -824,4 +831,4 @@ pushAll(errors, codomainValidation.value);

}
return errors.length ? exports.failures(errors) : exports.success((changed ? a : o));
}
return errors.length > 0 ? exports.failures(errors) : exports.success((changed ? a : o));
}, domain.encode === exports.identity && codomain.encode === exports.identity

@@ -873,16 +880,13 @@ ? exports.identity

var type_3 = codecs[i];
var validation = type_3.validate(u, exports.appendContext(c, String(i), type_3));
var validation = type_3.validate(u, exports.appendContext(c, String(i), type_3, u));
if (validation.isRight()) {
return validation;
}
else {
pushAll(errors, validation.value);
}
pushAll(errors, validation.value);
}
return errors.length ? exports.failures(errors) : exports.failure(u, c);
return errors.length > 0 ? exports.failures(errors) : exports.failure(u, c);
}, useIdentity(codecs, len)
? exports.identity
: function (a) {
var i = 0;
for (; i < len - 1; i++) {
for (var i = 0; i < len - 1; i++) {
var type_4 = codecs[i];

@@ -893,3 +897,3 @@ if (type_4.is(a)) {

}
return codecs[i].encode(a);
return a;
}, codecs);

@@ -911,29 +915,32 @@ };

exports.IntersectionType = IntersectionType;
var mergeAll = function (us) {
var r = us[0];
for (var i = 1; i < us.length; i++) {
var u = us[i];
if (u !== r) {
r = Object.assign(r, u);
}
}
return r;
};
function intersection(codecs, name) {
if (name === void 0) { name = "(" + codecs.map(function (type) { return type.name; }).join(' & ') + ")"; }
var len = codecs.length;
return new IntersectionType(name, function (u) { return (len === 0 ? false : codecs.every(function (type) { return type.is(u); })); }, function (u, c) {
var a = u;
var errors = [];
for (var i = 0; i < len; i++) {
var type_5 = codecs[i];
var validation = type_5.validate(a, exports.appendContext(c, String(i), type_5));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
a = validation.value;
}
}
return errors.length ? exports.failures(errors) : len === 0 ? exports.failure(u, c) : exports.success(a);
}, useIdentity(codecs, len)
? exports.identity
: function (a) {
var s = a;
return new IntersectionType(name, function (u) { return codecs.every(function (type) { return type.is(u); }); }, codecs.length === 0
? exports.success
: function (u, c) {
var us = [];
var errors = [];
for (var i = 0; i < len; i++) {
var type_6 = codecs[i];
s = type_6.encode(s);
var codec = codecs[i];
var validation = codec.validate(u, exports.appendContext(c, String(i), codec, u));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
us.push(validation.value);
}
}
return s;
}, codecs);
return errors.length > 0 ? exports.failures(errors) : exports.success(mergeAll(us));
}, codecs.length === 0 ? exports.identity : function (a) { return mergeAll(codecs.map(function (codec) { return codec.encode(a); })); }, codecs);
}

@@ -959,33 +966,28 @@ exports.intersection = intersection;

return new TupleType(name, function (u) { return exports.UnknownArray.is(u) && u.length === len && codecs.every(function (type, i) { return type.is(u[i]); }); }, function (u, c) {
var arrayValidation = exports.UnknownArray.validate(u, c);
if (arrayValidation.isLeft()) {
return arrayValidation;
var unknownArrayValidation = exports.UnknownArray.validate(u, c);
if (unknownArrayValidation.isLeft()) {
return unknownArrayValidation;
}
else {
var as = arrayValidation.value;
var t = as;
var errors = [];
for (var i = 0; i < len; i++) {
var a = as[i];
var type_7 = codecs[i];
var validation = type_7.validate(a, exports.appendContext(c, String(i), type_7));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var va = validation.value;
if (va !== a) {
/* istanbul ignore next */
if (t === as) {
t = as.slice();
}
t[i] = va;
var us = unknownArrayValidation.value;
var as = us.length > len ? us.slice(0, len) : us; // strip additional components
var errors = [];
for (var i = 0; i < len; i++) {
var a = us[i];
var type_5 = codecs[i];
var validation = type_5.validate(a, exports.appendContext(c, String(i), type_5, a));
if (validation.isLeft()) {
pushAll(errors, validation.value);
}
else {
var va = validation.value;
if (va !== a) {
/* istanbul ignore next */
if (as === us) {
as = us.slice();
}
as[i] = va;
}
}
if (as.length > len) {
errors.push({ value: as[len], context: exports.appendContext(c, String(len), exports.never) });
}
return errors.length ? exports.failures(errors) : exports.success(t);
}
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);

@@ -1047,5 +1049,3 @@ }

}
else {
return x;
}
return x;
});

@@ -1056,2 +1056,3 @@ }, arrayType.encode, codec);

* @since 1.0.0
* @deprecated
*/

@@ -1070,10 +1071,7 @@ var StrictType = /** @class */ (function (_super) {

/**
* Specifies that only the given properties are allowed
* @deprecated use `exact` instead
* Strips additional properties
* @since 1.0.0
*/
exports.strict = function (props, name) {
if (name === void 0) { name = "StrictType<" + getNameFromProps(props) + ">"; }
var exactType = exact(exports.type(props));
return new StrictType(name, exactType.is, exactType.validate, exactType.encode, props);
return exports.exact(exports.type(props), name);
};

@@ -1088,17 +1086,15 @@ /** @internal */

}
else if (b === monoidIndexRecord.empty) {
if (b === monoidIndexRecord.empty) {
return a;
}
else {
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];
}
var r = cloneIndexRecord(a);
for (var k in b) {
if (r.hasOwnProperty(k)) {
(_a = r[k]).push.apply(_a, b[k]);
}
return r;
else {
r[k] = b[k];
}
}
return r;
},

@@ -1145,12 +1141,12 @@ empty: exports.emptyIndexRecord

}
else if (isIntersectionCodec(codec)) {
if (isIntersectionCodec(codec)) {
return foldMapIndexRecord(codec.types, function (type) { return getCodecIndexRecord(type, origin, codec); });
}
else if (isUnionCodec(codec)) {
if (isUnionCodec(codec)) {
return foldMapIndexRecord(codec.types, function (type) { return getCodecIndexRecord(type, origin, type); });
}
else if (isExactCodec(codec) || isRefinementCodec(codec)) {
if (isExactCodec(codec) || isRefinementCodec(codec)) {
return getCodecIndexRecord(codec.type, origin, codec);
}
else if (isRecursiveCodec(codec)) {
if (isRecursiveCodec(codec)) {
var indexRecord = codec.getIndexRecord();

@@ -1162,5 +1158,3 @@ if (codec !== origin) {

}
else {
return monoidIndexRecord.empty;
}
return monoidIndexRecord.empty;
};

@@ -1229,15 +1223,11 @@ var isRecursiveCodecIndexable = true;

});
var find = function (tagValue) {
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 [i, codecs[position]];
return position;
}
}
};
var isTagValue = function (u) { return find(u) !== undefined; };
var TagValue = new Type(index.map(function (_a) {
var v = _a[0];
return JSON.stringify(v);
}).join(' | '), isTagValue, function (u, c) { return (isTagValue(u) ? exports.success(u) : exports.failure(u, c)); }, exports.identity);
var isTagValue = function (u) { return findIndex(u) !== undefined; };
return new TaggedUnionType(name, function (u) {

@@ -1248,4 +1238,4 @@ if (!exports.UnknownRecord.is(u)) {

var tagValue = u[tag];
var type = find(tagValue);
return type ? type[1].is(u) : false;
var index = findIndex(tagValue);
return index !== undefined ? codecs[index].is(u) : false;
}, function (u, c) {

@@ -1256,13 +1246,11 @@ var dictionaryResult = exports.UnknownRecord.validate(u, c);

}
else {
var d = dictionaryResult.value;
var tagValue = d[tag];
var tagValueValidation = TagValue.validate(d[tag], exports.appendContext(c, tag, TagValue));
if (tagValueValidation.isLeft()) {
return tagValueValidation;
}
var _a = find(tagValue), i = _a[0], type_8 = _a[1];
return type_8.validate(d, exports.appendContext(c, String(i), type_8));
var d = dictionaryResult.value;
var tagValue = d[tag];
if (!isTagValue(tagValue)) {
return exports.failure(u, c);
}
}, useIdentity(codecs, len) ? exports.identity : function (a) { return find(a[tag])[1].encode(a); }, codecs, tag);
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);
};

@@ -1296,5 +1284,3 @@ /**

}
else {
return getTaggedUnion(indexRecord[tag], tag, codecs, name);
}
return getTaggedUnion(indexRecord[tag], tag, codecs, name);
};

@@ -1328,29 +1314,45 @@ /**

};
var stripKeys = function (o, props) {
var keys = Object.getOwnPropertyNames(o);
var shouldStrip = false;
var r = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!hasOwnProperty.call(props, key)) {
shouldStrip = true;
}
else {
r[key] = o[key];
}
}
return shouldStrip ? r : o;
};
var getExactTypeName = function (codec) {
if (isInterfaceCodec(codec)) {
return "{| " + getNameFromProps(codec.props) + " |}";
}
else if (isPartialCodec(codec)) {
return getPartialTypeName("{| " + getNameFromProps(codec.props) + " |}");
}
return "Exact<" + codec.name + ">";
};
/**
* Strips additional properties
* @since 1.1.0
*/
function exact(codec, name) {
if (name === void 0) { name = "ExactType<" + codec.name + ">"; }
exports.exact = function (codec, name) {
if (name === void 0) { name = getExactTypeName(codec); }
var props = getProps(codec);
return new ExactType(name, function (u) { return codec.is(u) && Object.getOwnPropertyNames(u).every(function (k) { return hasOwnProperty.call(props, k); }); }, function (u, c) {
var looseValidation = codec.validate(u, c);
if (looseValidation.isLeft()) {
return looseValidation;
var unknownRecordValidation = exports.UnknownRecord.validate(u, c);
if (unknownRecordValidation.isLeft()) {
return unknownRecordValidation;
}
else {
var o = looseValidation.value;
var keys = Object.getOwnPropertyNames(o);
var len = keys.length;
var errors = [];
for (var i = 0; i < len; i++) {
var key = keys[i];
if (!hasOwnProperty.call(props, key)) {
errors.push({ value: o[key], context: exports.appendContext(c, key, exports.never) });
}
}
return errors.length ? exports.failures(errors) : exports.success(o);
var validation = codec.validate(u, c);
if (validation.isLeft()) {
return validation;
}
}, codec.encode, codec);
}
exports.exact = exact;
return exports.success(stripKeys(validation.value, props));
}, function (a) { return codec.encode(stripKeys(a, props)); }, codec);
};
/**

@@ -1357,0 +1359,0 @@ * Drops the codec "kind"

@@ -5,3 +5,9 @@ "use strict";

function stringify(v) {
return typeof v === 'function' ? index_1.getFunctionName(v) : JSON.stringify(v);
if (typeof v === 'function') {
return index_1.getFunctionName(v);
}
if (typeof v === 'number' && !isFinite(v)) {
return v > 0 ? 'Infinity' : '-Infinity';
}
return JSON.stringify(v);
}

@@ -8,0 +14,0 @@ function getContextPath(context) {

{
"name": "io-ts",
"version": "1.7.1",
"version": "1.8.0",
"description": "TypeScript compatible runtime type system for IO validation",

@@ -42,3 +42,3 @@ "files": [

"benchmark": "2.1.4",
"dtslint": "^0.4.2",
"dtslint": "github:gcanti/dtslint",
"jest": "^23.6.0",

@@ -45,0 +45,0 @@ "mocha": "^5.2.0",

@@ -208,31 +208,32 @@ [![build status](https://img.shields.io/travis/gcanti/io-ts/master.svg?style=flat-square)](https://travis-ci.org/gcanti/io-ts)

| Type | TypeScript | codec / combinator |
| ----------------- | --------------------------------------- | ----------------------------------------------------- |
| null | `null` | `t.null` or `t.nullType` |
| undefined | `undefined` | `t.undefined` |
| void | `void` | `t.void` or `t.voidType` |
| string | `string` | `t.string` |
| number | `number` | `t.number` |
| boolean | `boolean` | `t.boolean` |
| unknown | `unknown` | t.unknown |
| never | `never` | `t.never` |
| object | `object` | `t.object` |
| integer | ✘ | `t.Integer` |
| array of unknown | `Array<unknown>` | `t.UnknownArray` |
| array of type | `Array<A>` | `t.array(A)` |
| record of unknown | `Record<string, unknown>` | `t.UnknownRecord` |
| record of type | `Record<K, A>` | `t.record(K, A)` |
| function | `Function` | `t.Function` |
| literal | `'s'` | `t.literal('s')` |
| partial | `Partial<{ name: string }>` | `t.partial({ name: t.string })` |
| readonly | `Readonly<T>` | `t.readonly(T)` |
| readonly array | `ReadonlyArray<number>` | `t.readonlyArray(t.number)` |
| type alias | `type A = { name: string }` | `t.type({ name: t.string })` |
| tuple | `[ A, B ]` | `t.tuple([ A, B ])` |
| union | `A \| B` | `t.union([ A, B ])` or `t.taggedUnion(tag, [ A, B ])` |
| intersection | `A & B` | `t.intersection([ A, B ])` |
| keyof | `keyof M` | `t.keyof(M)` |
| recursive types | see [Recursive types](#recursive-types) | `t.recursion(name, definition)` |
| refinement | ✘ | `t.refinement(A, predicate)` |
| exact types | ✘ | `t.exact(type)` |
| Type | TypeScript | codec / combinator |
| --------------------------- | --------------------------- | -------------------------------------------------------------------- |
| null | `null` | `t.null` or `t.nullType` |
| undefined | `undefined` | `t.undefined` |
| void | `void` | `t.void` or `t.voidType` |
| string | `string` | `t.string` |
| number | `number` | `t.number` |
| boolean | `boolean` | `t.boolean` |
| unknown | `unknown` | `t.unknown` |
| never | `never` | `t.never` |
| object | `object` | `t.object` |
| array of unknown | `Array<unknown>` | `t.UnknownArray` |
| array of type | `Array<A>` | `t.array(A)` |
| record of unknown | `Record<string, unknown>` | `t.UnknownRecord` |
| record of type | `Record<K, A>` | `t.record(K, A)` |
| function | `Function` | `t.Function` |
| literal | `'s'` | `t.literal('s')` |
| partial | `Partial<{ name: string }>` | `t.partial({ name: t.string })` |
| readonly | `Readonly<A>` | `t.readonly(A)` |
| readonly array | `ReadonlyArray<A>` | `t.readonlyArray(A)` |
| type alias | `type T = { name: A }` | `t.type({ name: A })` |
| tuple | `[ A, B ]` | `t.tuple([ A, B ])` |
| union | `A \| B` | `t.union([ A, B ])` or `t.taggedUnion(tag, [ A, B ])` |
| intersection | `A & B` | `t.intersection([ A, B ])` |
| keyof | `keyof M` | `t.keyof(M)` |
| recursive types | ✘ | `t.recursion(name, definition)` |
| branded types / refinements | ✘ | `t.brand(A, predicate, brand)` |
| integer | ✘ | `t.Int` (built-in branded codec) |
| exact types | ✘ | `t.exact(type)` |
| strict | ✘ | `t.strict({ name: A })` (an alias of `t.exact(t.type({ name: A })))` |

@@ -307,34 +308,44 @@ # Recursive types

# Refinements
# Branded types / Refinements
You can refine a type (_any_ type) using the `refinement` combinator
You can refine a codec (_any_ codec) using the `brand` combinator
```ts
const Positive = t.refinement(t.number, n => n >= 0, 'Positive')
const Positive = t.brand(t.number, n => n >= 0, 'Positive')
const Adult = t.refinement(Person, person => person.age >= 18, 'Adult')
```
type Positive = t.TypeOf<typeof Positive>
/*
same as
type Positive = number & t.Brand<"Positive">
*/
# Exact types
const PositiveInt = t.intersection([t.Int, Positive])
You can make a codec alias exact (which means that only the given properties are allowed) using the `exact` combinator
type PositiveInt = t.TypeOf<typeof PositiveInt>
/*
same as
type PositiveInt = number & t.Brand<"Int"> & t.Brand<"Positive">
*/
```ts
const Person = t.type({
name: t.string,
age: t.number
age: PositiveInt
})
const ExactPerson = t.exact(Person)
const Adult = t.brand(Person, person => person.age >= 18, 'Adult')
Person.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // ok
ExactPerson.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // fails
type Adult = t.TypeOf<typeof Adult>
/*
same as
type Adult = {
name: string;
age: number & t.Brand<"Int"> & t.Brand<"Positive">;
} & t.Brand<"Adult">
*/
```
# Strict types (deprecated)
# Exact types
**Note**. This combinator is deprecated, use `exact` instead.
You can make a codec exact (which means that additional properties are stripped) using the `exact` combinator
You can make a codec strict (which means that only the given properties are allowed) using the `strict` combinator
```ts

@@ -346,6 +357,6 @@ const Person = t.type({

const StrictPerson = t.strict(Person.props)
const ExactPerson = t.exact(Person)
Person.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // ok
StrictPerson.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // fails
Person.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // ok, result is right({ name: 'Giulio', age: 43, surname: 'Canti' })
ExactPerson.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // ok but result is right({ name: 'Giulio', age: 43 })
```

@@ -405,9 +416,9 @@

// represents a Date from an ISO string
const DateFromString = new t.Type<Date, string>(
const DateFromString = new t.Type<Date, string, unknown>(
'DateFromString',
(m): m is Date => m instanceof Date,
(m, c) =>
t.string.validate(m, c).chain(s => {
(u): u is Date => u instanceof Date,
(u, c) =>
t.string.validate(u, c).chain(s => {
const d = new Date(s)
return isNaN(d.getTime()) ? t.failure(s, c) : t.success(d)
return isNaN(d.getTime()) ? t.failure(u, c) : t.success(d)
}),

@@ -455,2 +466,3 @@ a => a.toISOString()

})
const Links = t.interface({

@@ -553,3 +565,2 @@ previous: t.string,

- unique check for free
- better performance
- quick info stays responsive
- better performance, `O(log(n))` vs `O(n)`
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc