Comparing version 2.4.1 to 2.5.0
@@ -15,2 +15,11 @@ # Changelog | ||
## v2.5.0 | ||
- **New Feature** | ||
- check if the type returned by a union dispatch function is correct, fix #136 (thanks @fcracker79) | ||
- added `refinement` alias to `subtype` (which is deprecated), fix #140 | ||
- **Internal** | ||
- optimisations: for identity types return early in production, fix #135 (thanks @fcracker79) | ||
- exposed `getDefaultName` on combinator constructors | ||
## v2.4.1 | ||
@@ -17,0 +26,0 @@ |
36
GUIDE.md
@@ -27,11 +27,11 @@ # Setup | ||
* `t.String`: strings (short alias `t.Str`) | ||
* `t.Number`: numbers (short alias `t.Num`) | ||
* `t.Boolean`: booleans (short alias `t.Bool`) | ||
* `t.Array`: arrays (short alias `t.Arr`) | ||
* `t.Object`: plain objects (short alias `t.Obj`) | ||
* `t.Function`: functions (short alias `t.Func`) | ||
* `t.Error`: errors (short alias `t.Err`) | ||
* `t.RegExp`: regular expressions (short alias `t.Re`) | ||
* `t.Date`: dates (short alias `t.Dat`) | ||
* `t.String`: strings (deprecated alias `t.Str`) | ||
* `t.Number`: numbers (deprecated alias `t.Num`) | ||
* `t.Boolean`: booleans (deprecated alias `t.Bool`) | ||
* `t.Array`: arrays (deprecated alias `t.Arr`) | ||
* `t.Object`: plain objects (deprecated alias `t.Obj`) | ||
* `t.Function`: functions (deprecated alias `t.Func`) | ||
* `t.Error`: errors (deprecated alias `t.Err`) | ||
* `t.RegExp`: regular expressions (deprecated alias `t.Re`) | ||
* `t.Date`: dates (deprecated alias `t.Dat`) | ||
@@ -43,3 +43,3 @@ There are 2 additional irriducible types defined in tcomb: | ||
* `t.Nil`: `null` or `undefined` | ||
* `t.Any`: any type | ||
* `t.Any`: any value | ||
@@ -150,5 +150,5 @@ ## Type checking with the `is` function | ||
## The subtype combinator | ||
## The refinement combinator (deprecated alias `subtype`) | ||
You can refine a type using the `subtype(type, predicate, name)` combinator where: | ||
You can refine a type using the `refinement(type, predicate, name)` combinator where: | ||
@@ -163,3 +163,3 @@ * `type` is a type already defined | ||
// defines a type representing positive numbers | ||
var Positive = t.subtype(t.Number, (n) => n >= 0, 'Positive'); | ||
var Positive = t.refinement(t.Number, (n) => n >= 0, 'Positive'); | ||
@@ -170,3 +170,3 @@ Positive.is(1); // => true | ||
Subtypes have the following `meta` object: | ||
Refinements have the following `meta` object: | ||
@@ -446,4 +446,4 @@ ```js | ||
```js | ||
var Min = t.subtype(t.String, function (s) { return s.length > 2; }, 'Min'); | ||
var Max = t.subtype(t.String, function (s) { return s.length < 5; }, 'Max'); | ||
var Min = t.refinement(t.String, function (s) { return s.length > 2; }, 'Min'); | ||
var Max = t.refinement(t.String, function (s) { return s.length < 5; }, 'Max'); | ||
var MinMax = t.intersection([Min, Max], 'MinMax'); | ||
@@ -534,3 +534,3 @@ | ||
// An `ExcitedString` is a `t.String` containing an exclamation mark | ||
var ExcitedString = t.subtype(t.String, function (s) { return s.indexOf('!') !== -1; }, 'ExcitedString'); | ||
var ExcitedString = t.refinement(t.String, function (s) { return s.indexOf('!') !== -1; }, 'ExcitedString'); | ||
@@ -573,3 +573,3 @@ // An `Exciter` takes a `t.String` and returns an `ExcitedString` | ||
// Raises error: | ||
// Invalid `Hello?` supplied to `ExcitedString`, insert a valid value for the subtype | ||
// Invalid `Hello?` supplied to `ExcitedString`, insert a valid value for the refinement | ||
simpleQuestionator('Hello'); | ||
@@ -576,0 +576,0 @@ |
391
index.js
@@ -5,3 +5,3 @@ /*! @preserve | ||
* | ||
* Copyright (c) 2014 Giulio Canti | ||
* Copyright (c) 2014-2015 Giulio Canti | ||
* | ||
@@ -12,7 +12,8 @@ */ | ||
// configurable | ||
// overrideable by the user | ||
exports.stringify = function stringify(x) { | ||
try { // handle "Converting circular structure to JSON" error | ||
return JSON.stringify(x, null, 2); | ||
} catch (e) { | ||
} | ||
catch (e) { | ||
return String(x); | ||
@@ -22,6 +23,2 @@ } | ||
function isInstanceOf(x, constructor) { | ||
return x instanceof constructor; | ||
} | ||
function isNil(x) { | ||
@@ -48,3 +45,3 @@ return x === null || x === void 0; | ||
function isArray(x) { | ||
return isInstanceOf(x, Array); | ||
return x instanceof Array; | ||
} | ||
@@ -61,11 +58,11 @@ | ||
function isStruct(x) { | ||
return isType(x) && (x.meta.kind === 'struct'); | ||
return isType(x) && ( x.meta.kind === 'struct' ); | ||
} | ||
function isMaybe(x) { | ||
return isType(x) && (x.meta.kind === 'maybe'); | ||
return isType(x) && ( x.meta.kind === 'maybe' ); | ||
} | ||
function isUnion(x) { | ||
return isType(x) && (x.meta.kind === 'union'); | ||
return isType(x) && ( x.meta.kind === 'union' ); | ||
} | ||
@@ -77,7 +74,19 @@ | ||
// Returns true if x is of type `type` | ||
// returns true if x is an instance of type | ||
function is(x, type) { | ||
return isType(type) ? type.is(x) : isInstanceOf(x, type); // type should be a class constructor | ||
if (isType(type)) { | ||
return type.is(x); | ||
} | ||
return x instanceof type; // type should be a class constructor | ||
} | ||
// return true if the type constructor behaves like the identity function (exceptions are the structs) | ||
function isIdentity(type) { | ||
if (isType(type)) { | ||
return type.meta.identity; | ||
} | ||
return true; // ES6 classes are identity for tcomb | ||
} | ||
// creates an instance of a type, handling the optional new operator | ||
function create(type, value, path) { | ||
@@ -90,5 +99,5 @@ if (isType(type)) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
// type should be a class constructor and value some instance, just check membership and return the value | ||
// here type should be a class constructor and value some instance, just check membership and return the value | ||
path = path || [getFunctionName(type)]; | ||
assert(isInstanceOf(value, type), function () { return 'Invalid value ' + exports.stringify(value) + ' supplied to ' + path.join('/'); }); | ||
assert(value instanceof type, function () { return 'Invalid value ' + exports.stringify(value) + ' supplied to ' + path.join('/'); }); | ||
} | ||
@@ -104,7 +113,9 @@ | ||
function getTypeName(constructor) { | ||
if (isType(constructor)) { return constructor.displayName; } | ||
if (isType(constructor)) { | ||
return constructor.displayName; | ||
} | ||
return getFunctionName(constructor); | ||
} | ||
// configurable | ||
// overrideable by the user | ||
exports.fail = function fail(message) { | ||
@@ -116,6 +127,6 @@ throw new TypeError('[tcomb] ' + message); | ||
if (guard !== true) { | ||
if (isFunction(message)) { | ||
if (isFunction(message)) { // handle lazy messages | ||
message = message(); | ||
} | ||
else if (isNil(message)) { | ||
else if (isNil(message)) { // use a default message | ||
message = 'Assert failed (turn on "Pause on exceptions" in your Source panel)'; | ||
@@ -127,3 +138,3 @@ } | ||
// safe mixin: cannot override props unless specified | ||
// safe mixin, cannot override props unless specified | ||
function mixin(target, source, overwrite) { | ||
@@ -145,8 +156,12 @@ if (isNil(source)) { return target; } | ||
function forbidNewOperator(x, type) { | ||
assert(!isInstanceOf(x, type), function () { return 'Cannot use the new operator to instantiate the type ' + getTypeName(type); }); | ||
assert(!(x instanceof type), function () { return 'Cannot use the new operator to instantiate the type ' + getTypeName(type); }); | ||
} | ||
function getShallowCopy(x) { | ||
if (isArray(x)) { return x.concat(); } | ||
if (isObject(x)) { return mixin({}, x); } | ||
if (isArray(x)) { | ||
return x.concat(); | ||
} | ||
if (isObject(x)) { | ||
return mixin({}, x); | ||
} | ||
return x; | ||
@@ -275,3 +290,4 @@ } | ||
kind: 'irreducible', | ||
name: name | ||
name: name, | ||
identity: true | ||
}; | ||
@@ -305,19 +321,13 @@ | ||
var Err = irreducible('Error', function (x) { | ||
return isInstanceOf(x, Error); | ||
return x instanceof Error; | ||
}); | ||
var Re = irreducible('RegExp', function (x) { | ||
return isInstanceOf(x, RegExp); | ||
return x instanceof RegExp; | ||
}); | ||
var Dat = irreducible('Date', function (x) { | ||
return isInstanceOf(x, Date); | ||
return x instanceof Date; | ||
}); | ||
function getDefaultStructName(props) { | ||
return '{' + Object.keys(props).map(function (prop) { | ||
return prop + ': ' + getTypeName(props[prop]); | ||
}).join(', ') + '}'; | ||
} | ||
function struct(props, name) { | ||
@@ -330,7 +340,7 @@ | ||
var displayName = name || getDefaultStructName(props); | ||
var displayName = name || struct.getDefaultName(props); | ||
function Struct(value, path) { | ||
if (Struct.is(value)) { // makes Struct idempotent | ||
if (Struct.is(value)) { // implements idempotency | ||
return value; | ||
@@ -344,3 +354,3 @@ } | ||
if (!isInstanceOf(this, Struct)) { // makes `new` optional | ||
if (!(this instanceof Struct)) { // `new` is optional | ||
return new Struct(value); | ||
@@ -366,3 +376,4 @@ } | ||
props: props, | ||
name: name | ||
name: name, | ||
identity: false | ||
}; | ||
@@ -373,3 +384,3 @@ | ||
Struct.is = function (x) { | ||
return isInstanceOf(x, Struct); | ||
return x instanceof Struct; | ||
}; | ||
@@ -404,5 +415,7 @@ | ||
function getDefaultUnionName(types) { | ||
return types.map(getTypeName).join(' | '); | ||
} | ||
struct.getDefaultName = function (props) { | ||
return '{' + Object.keys(props).map(function (prop) { | ||
return prop + ': ' + getTypeName(props[prop]); | ||
}).join(', ') + '}'; | ||
}; | ||
@@ -416,8 +429,11 @@ function union(types, name) { | ||
var displayName = name || getDefaultUnionName(types); | ||
var displayName = name || union.getDefaultName(types); | ||
var identity = types.every(isIdentity); | ||
function Union(value, path) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
forbidNewOperator(this, Union); | ||
if (process.env.NODE_ENV === 'production') { | ||
if (identity) { | ||
return value; | ||
} | ||
} | ||
@@ -428,4 +444,6 @@ | ||
if (process.env.NODE_ENV !== 'production') { | ||
forbidNewOperator(this, Union); | ||
path = path || [displayName]; | ||
assert(isType(type), function () { return 'Invalid value ' + exports.stringify(value) + ' supplied to ' + path.join('/'); }); | ||
assert(isType(type), function () { return 'Invalid value ' + exports.stringify(value) + ' supplied to ' + path.join('/') + ' (no constructor found)'; }); | ||
assert(types.some(function (t) { return t === type; }), function () { return 'Invalid constructor ' + getTypeName(type) + ' returned by ' + path.join('/') + '.dispatch(x) function'; }); | ||
path[path.length - 1] += '(' + getTypeName(type) + ')'; | ||
@@ -440,3 +458,4 @@ } | ||
types: types, | ||
name: name | ||
name: name, | ||
identity: identity | ||
}; | ||
@@ -455,3 +474,3 @@ | ||
var type = types[i]; | ||
if (isUnion(type)) { | ||
if (isUnion(type)) { // handle union of unions | ||
var t = type.dispatch(x); | ||
@@ -475,5 +494,5 @@ if (!isNil(t)) { | ||
function getDefaultIntersectionName(types) { | ||
return types.map(getTypeName).join(' & '); | ||
} | ||
union.getDefaultName = function (types) { | ||
return types.map(getTypeName).join(' | '); | ||
}; | ||
@@ -487,3 +506,3 @@ function intersection(types, name) { | ||
var displayName = name || getDefaultIntersectionName(types); | ||
var displayName = name || intersection.getDefaultName(types); | ||
@@ -504,3 +523,4 @@ function Intersection(value, path) { | ||
types: types, | ||
name: name | ||
name: name, | ||
identity: true | ||
}; | ||
@@ -523,12 +543,8 @@ | ||
function getDefaultMaybeName(type) { | ||
return '?' + getTypeName(type); | ||
} | ||
intersection.getDefaultName = function (types) { | ||
return types.map(getTypeName).join(' & '); | ||
}; | ||
function maybe(type, name) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assert(isFunction(type), function () { return 'Invalid argument type ' + exports.stringify(type) + ' supplied to maybe(type, [name]) combinator (expected a type)'; }); | ||
} | ||
if (isMaybe(type) || type === Any || type === Nil) { // makes the combinator idempotent and handle Any, Nil | ||
@@ -539,6 +555,7 @@ return type; | ||
if (process.env.NODE_ENV !== 'production') { | ||
assert(isFunction(type), function () { return 'Invalid argument type ' + exports.stringify(type) + ' supplied to maybe(type, [name]) combinator (expected a type)'; }); | ||
assert(isTypeName(name), function () { return 'Invalid argument name ' + exports.stringify(name) + ' supplied to maybe(type, [name]) combinator (expected a string)'; }); | ||
} | ||
var displayName = name || getDefaultMaybeName(type); | ||
var displayName = name || maybe.getDefaultName(type); | ||
@@ -555,3 +572,4 @@ function Maybe(value, path) { | ||
type: type, | ||
name: name | ||
name: name, | ||
identity: isIdentity(type) | ||
}; | ||
@@ -568,5 +586,5 @@ | ||
function getDefaultEnumsName(map) { | ||
return Object.keys(map).map(function (k) { return exports.stringify(k); }).join(' | '); | ||
} | ||
maybe.getDefaultName = function (type) { | ||
return '?' + getTypeName(type); | ||
}; | ||
@@ -580,3 +598,3 @@ function enums(map, name) { | ||
var displayName = name || getDefaultEnumsName(map); | ||
var displayName = name || enums.getDefaultName(map); | ||
@@ -597,3 +615,4 @@ function Enums(value, path) { | ||
map: map, | ||
name: name | ||
name: name, | ||
identity: true | ||
}; | ||
@@ -610,2 +629,6 @@ | ||
enums.getDefaultName = function (map) { | ||
return Object.keys(map).map(function (k) { return exports.stringify(k); }).join(' | '); | ||
}; | ||
enums.of = function (keys, name) { | ||
@@ -620,6 +643,2 @@ keys = isString(keys) ? keys.split(' ') : keys; | ||
function getDefaultTupleName(types) { | ||
return '[' + types.map(getTypeName).join(', ') + ']'; | ||
} | ||
function tuple(types, name) { | ||
@@ -632,12 +651,13 @@ | ||
var displayName = name || getDefaultTupleName(types); | ||
var displayName = name || tuple.getDefaultName(types); | ||
var identity = types.every(isIdentity); | ||
function isTuple(x) { | ||
return types.every(function (type, i) { | ||
return is(x[i], type); | ||
}); | ||
} | ||
function Tuple(value, path) { | ||
if (process.env.NODE_ENV === 'production') { | ||
if (identity) { | ||
return value; | ||
} | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -648,21 +668,21 @@ path = path || [displayName]; | ||
if (isTuple(value)) { // makes Tuple idempotent | ||
if (process.env.NODE_ENV !== 'production') { | ||
Object.freeze(value); | ||
} | ||
return value; | ||
var idempotent = true; | ||
var ret = []; | ||
for (var i = 0, len = types.length; i < len; i++) { | ||
var expected = types[i]; | ||
var actual = value[i]; | ||
var instance = create(expected, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(i + ': ' + getTypeName(expected)) : null )); | ||
idempotent = idempotent && ( actual === instance ); | ||
ret.push(instance); | ||
} | ||
var arr = [], expected, actual; | ||
for (var i = 0, len = types.length; i < len; i++) { | ||
expected = types[i]; | ||
actual = value[i]; | ||
arr.push(create(expected, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(i + ': ' + getTypeName(expected)) : null ))); | ||
if (idempotent) { // implements idempotency | ||
ret = value; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
Object.freeze(arr); | ||
Object.freeze(ret); | ||
} | ||
return arr; | ||
return ret; | ||
} | ||
@@ -673,3 +693,4 @@ | ||
types: types, | ||
name: name | ||
name: name, | ||
identity: identity | ||
}; | ||
@@ -682,3 +703,5 @@ | ||
x.length === types.length && | ||
isTuple(x); | ||
types.every(function (type, i) { | ||
return is(x[i], type); | ||
}); | ||
}; | ||
@@ -693,20 +716,21 @@ | ||
function getDefaultSubtypeName(type, predicate) { | ||
return '{' + getTypeName(type) + ' | ' + getFunctionName(predicate) + '}'; | ||
} | ||
tuple.getDefaultName = function (types) { | ||
return '[' + types.map(getTypeName).join(', ') + ']'; | ||
}; | ||
function subtype(type, predicate, name) { | ||
function refinement(type, predicate, name) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
assert(isFunction(type), function () { return 'Invalid argument type ' + exports.stringify(type) + ' supplied to subtype(type, predicate, [name]) combinator (expected a type)'; }); | ||
assert(isFunction(predicate), function () { return 'Invalid argument predicate supplied to subtype(type, predicate, [name]) combinator (expected a function)'; }); | ||
assert(isTypeName(name), function () { return 'Invalid argument name ' + exports.stringify(name) + ' supplied to subtype(type, predicate, [name]) combinator (expected a string)'; }); | ||
assert(isFunction(type), function () { return 'Invalid argument type ' + exports.stringify(type) + ' supplied to refinement(type, predicate, [name]) combinator (expected a type)'; }); | ||
assert(isFunction(predicate), function () { return 'Invalid argument predicate supplied to refinement(type, predicate, [name]) combinator (expected a function)'; }); | ||
assert(isTypeName(name), function () { return 'Invalid argument name ' + exports.stringify(name) + ' supplied to refinement(type, predicate, [name]) combinator (expected a string)'; }); | ||
} | ||
var displayName = name || getDefaultSubtypeName(type, predicate); | ||
var displayName = name || refinement.getDefaultName(type, predicate); | ||
var identity = isIdentity(type); | ||
function Subtype(value, path) { | ||
function Refinement(value, path) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
forbidNewOperator(this, Subtype); | ||
forbidNewOperator(this, Refinement); | ||
path = path || [displayName]; | ||
@@ -724,25 +748,26 @@ } | ||
Subtype.meta = { | ||
Refinement.meta = { | ||
kind: 'subtype', | ||
type: type, | ||
predicate: predicate, | ||
name: name | ||
name: name, | ||
identity: identity | ||
}; | ||
Subtype.displayName = displayName; | ||
Refinement.displayName = displayName; | ||
Subtype.is = function (x) { | ||
Refinement.is = function (x) { | ||
return is(x, type) && predicate(x); | ||
}; | ||
Subtype.update = function (instance, spec) { | ||
return Subtype(exports.update(instance, spec)); | ||
Refinement.update = function (instance, spec) { | ||
return Refinement(exports.update(instance, spec)); | ||
}; | ||
return Subtype; | ||
return Refinement; | ||
} | ||
function getDefaultListName(type) { | ||
return 'Array<' + getTypeName(type) + '>'; | ||
} | ||
refinement.getDefaultName = function (type, predicate) { | ||
return '{' + getTypeName(type) + ' | ' + getFunctionName(predicate) + '}'; | ||
}; | ||
@@ -756,13 +781,14 @@ function list(type, name) { | ||
var displayName = name || getDefaultListName(type); | ||
var displayName = name || list.getDefaultName(type); | ||
var typeNameCache = getTypeName(type); | ||
var identity = isIdentity(type); // the list is identity iif type is identity | ||
function isList(x) { | ||
return x.every(function (e) { | ||
return is(e, type); | ||
}); | ||
} | ||
function List(value, path) { | ||
if (process.env.NODE_ENV === 'production') { | ||
if (identity) { | ||
return value; // just trust the input if elements must not be hydrated | ||
} | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -773,20 +799,20 @@ path = path || [displayName]; | ||
if (isList(value)) { // makes List idempotent | ||
if (process.env.NODE_ENV !== 'production') { | ||
Object.freeze(value); | ||
} | ||
return value; | ||
} | ||
var arr = []; | ||
var idempotent = true; // will remain true if I can reutilise the input | ||
var ret = []; // make a temporary copy, will be discarded if idempotent remains true | ||
for (var i = 0, len = value.length; i < len; i++ ) { | ||
var actual = value[i]; | ||
arr.push(create(type, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(i + ': ' + typeNameCache) : null ))); | ||
var instance = create(type, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(i + ': ' + typeNameCache) : null )); | ||
idempotent = idempotent && ( actual === instance ); | ||
ret.push(instance); | ||
} | ||
if (idempotent) { // implements idempotency | ||
ret = value; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
Object.freeze(arr); | ||
Object.freeze(ret); | ||
} | ||
return arr; | ||
return ret; | ||
} | ||
@@ -797,3 +823,4 @@ | ||
type: type, | ||
name: name | ||
name: name, | ||
identity: identity | ||
}; | ||
@@ -804,3 +831,5 @@ | ||
List.is = function (x) { | ||
return isArray(x) && isList(x); | ||
return isArray(x) && x.every(function (e) { | ||
return is(e, type); | ||
}); | ||
}; | ||
@@ -815,5 +844,5 @@ | ||
function getDefaultDictName(domain, codomain) { | ||
return '{[key: ' + getTypeName(domain) + ']: ' + getTypeName(codomain) + '}'; | ||
} | ||
list.getDefaultName = function (type) { | ||
return 'Array<' + getTypeName(type) + '>'; | ||
}; | ||
@@ -828,19 +857,15 @@ function dict(domain, codomain, name) { | ||
var displayName = name || getDefaultDictName(domain, codomain); | ||
var displayName = name || dict.getDefaultName(domain, codomain); | ||
var domainNameCache = getTypeName(domain); | ||
var codomainNameCache = getTypeName(codomain); | ||
var identity = isIdentity(domain) && isIdentity(codomain); | ||
function isDict(x) { | ||
for (var k in x) { | ||
if (x.hasOwnProperty(k)) { | ||
if (!is(k, domain) || !is(x[k], codomain)) { | ||
return false; | ||
} | ||
function Dict(value, path) { | ||
if (process.env.NODE_ENV === 'production') { | ||
if (identity) { | ||
return value; // just trust the input if elements must not be hydrated | ||
} | ||
} | ||
return true; | ||
} | ||
function Dict(value, path) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -851,10 +876,4 @@ path = path || [displayName]; | ||
if (isDict(value)) { // makes Dict idempotent | ||
if (process.env.NODE_ENV !== 'production') { | ||
Object.freeze(value); | ||
} | ||
return value; | ||
} | ||
var obj = {}; | ||
var idempotent = true; // will remain true if I can reutilise the input | ||
var ret = {}; // make a temporary copy, will be discarded if idempotent remains true | ||
for (var k in value) { | ||
@@ -864,11 +883,17 @@ if (value.hasOwnProperty(k)) { | ||
var actual = value[k]; | ||
obj[k] = create(codomain, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(k + ': ' + codomainNameCache) : null )); | ||
var instance = create(codomain, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(k + ': ' + codomainNameCache) : null )); | ||
idempotent = idempotent && ( actual === instance ); | ||
ret[k] = instance; | ||
} | ||
} | ||
if (idempotent) { // implements idempotency | ||
ret = value; | ||
} | ||
if (process.env.NODE_ENV !== 'production') { | ||
Object.freeze(obj); | ||
Object.freeze(ret); | ||
} | ||
return obj; | ||
return ret; | ||
} | ||
@@ -880,3 +905,4 @@ | ||
codomain: codomain, | ||
name: name | ||
name: name, | ||
identity: identity | ||
}; | ||
@@ -887,3 +913,13 @@ | ||
Dict.is = function (x) { | ||
return isObject(x) && isDict(x); | ||
if (!isObject(x)) { | ||
return false; | ||
} | ||
for (var k in x) { | ||
if (x.hasOwnProperty(k)) { | ||
if (!is(k, domain) || !is(x[k], codomain)) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
@@ -898,2 +934,6 @@ | ||
dict.getDefaultName = function (domain, codomain) { | ||
return '{[key: ' + getTypeName(domain) + ']: ' + getTypeName(codomain) + '}'; | ||
}; | ||
function isInstrumented(f) { | ||
@@ -903,6 +943,2 @@ return isFunction(f) && isObject(f.instrumentation); | ||
function getDefaultFuncName(domain, codomain) { | ||
return '(' + domain.map(getTypeName).join(', ') + ') => ' + getTypeName(codomain); | ||
} | ||
function func(domain, codomain, name) { | ||
@@ -918,8 +954,8 @@ | ||
var displayName = name || getDefaultFuncName(domain, codomain); | ||
var displayName = name || func.getDefaultName(domain, codomain); | ||
function FuncType(value, uncurried) { | ||
function FuncType(value, curried) { | ||
if (!isInstrumented(value)) { // automatically instrument the function | ||
return FuncType.of(value, uncurried); | ||
return FuncType.of(value, curried); | ||
} | ||
@@ -998,2 +1034,6 @@ | ||
func.getDefaultName = function (domain, codomain) { | ||
return '(' + domain.map(getTypeName).join(', ') + ') => ' + getTypeName(codomain); | ||
}; | ||
function match(x) { | ||
@@ -1038,19 +1078,19 @@ var type, guard, f, count; | ||
Nil: Nil, | ||
Str: Str, | ||
Str: Str, // deprecated | ||
String: Str, | ||
Num: Num, | ||
Num: Num, // deprecated | ||
Number: Num, | ||
Bool: Bool, | ||
Bool: Bool, // deprecated | ||
Boolean: Bool, | ||
Arr: Arr, | ||
Arr: Arr, // deprecated | ||
Array: Arr, | ||
Obj: Obj, | ||
Obj: Obj, // deprecated | ||
Object: Obj, | ||
Func: Func, | ||
Func: Func, // deprecated | ||
Function: Func, | ||
Err: Err, | ||
Err: Err, // deprecated | ||
Error: Err, | ||
Re: Re, | ||
Re: Re, // deprecated | ||
RegExp: Re, | ||
Dat: Dat, | ||
Dat: Dat, // deprecated | ||
Date: Dat, | ||
@@ -1063,3 +1103,4 @@ irreducible: irreducible, | ||
tuple: tuple, | ||
subtype: subtype, | ||
subtype: refinement, // deprecated | ||
refinement: refinement, | ||
list: list, | ||
@@ -1066,0 +1107,0 @@ dict: dict, |
{ | ||
"name": "tcomb", | ||
"version": "2.4.1", | ||
"version": "2.5.0", | ||
"description": "Type checking and DDD for JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -16,3 +16,3 @@ [![build status](https://img.shields.io/travis/gcanti/tcomb/master.svg?style=flat-square)](https://travis-ci.org/gcanti/tcomb) | ||
// a user defined type | ||
var Integer = t.subtype(t.Number, function (n) { return n % 1 === 0; }, 'Integer'); // <= give a name for better debug messages | ||
var Integer = t.refinement(t.Number, function (n) { return n % 1 === 0; }, 'Integer'); // <= give a name for better debug messages | ||
@@ -55,3 +55,3 @@ // a struct | ||
* enums | ||
* subtypes | ||
* refinements | ||
* unions | ||
@@ -58,0 +58,0 @@ * intersections |
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
59454
839