diff --git a/tcomb/tcomb-tests.ts b/tcomb/tcomb-tests.ts
index aeecdcb310..3a27ffc7fe 100644
--- a/tcomb/tcomb-tests.ts
+++ b/tcomb/tcomb-tests.ts
@@ -1,288 +1,1792 @@
// ReSharper disable InconsistentNaming
// ReSharper disable WrongExpressionStatement
+///
+///
+///
-import t = require("tcomb");
+// tests adapted from/for tcomb's test folder
-var Str = t.Str;
-var Num = t.Num;
+'use strict';
+import assert = require('assert');
+var t = require('../index');
+
+var Any = t.Any;
+var Nil = t.Nil;
var Bool = t.Bool;
+var Num = t.Num;
+var Str = t.Str;
var Arr = t.Arr;
var Obj = t.Obj;
var Func = t.Func;
var Err = t.Err;
var Re = t.Re;
var Dat = t.Dat;
-var Nil = t.Nil;
-var Any = t.Any;
-var Type = t.Type;
-
var struct = t.struct;
+var enums = t.enums;
+var union = t.union;
var tuple = t.tuple;
+var maybe = t.maybe;
+var subtype = t.subtype;
var list = t.list;
var dict = t.dict;
-var union = t.union;
-var maybe = t.maybe;
var func = t.func;
-var subtype = t.subtype;
+var getTypeName = t.getTypeName;
+var mixin = t.mixin;
+var format = t.format;
-Str.is("a string"); // => true
-Str.is(1); // => false
+//
+// setup
+//
-Num.is("a string"); // => true
-Num.is(1); // => false
+var ok = function (x:any) { assert.strictEqual(true, x); };
+var ko = function (x:any) { assert.strictEqual(false, x); };
+var eq = assert.deepEqual;
+var throwsWithMessage = function (f:any, message:any) {
+ assert.throws(f, function (err:any) {
+ ok(err instanceof Error);
+ eq(err.message, message);
+ return true;
+ });
+};
+var doesNotThrow = assert.doesNotThrow;
-Bool.is("a string"); // => true
-Bool.is(1); // => false
-
-Arr.is("a string"); // => true
-Arr.is(1); // => false
-
-Obj.is("a string"); // => true
-Obj.is(1); // => false
-
-Func.is("a string"); // => true
-Func.is(1); // => false
-
-Err.is("a string"); // => true
-Err.is(1); // => false
-
-Re.is("a string"); // => true
-Re.is(1); // => false
-
-Dat.is("a string"); // => true
-Dat.is(1); // => false
-
-Nil.is("a string"); // => true
-Nil.is(1); // => false
-
-Any.is("a string"); // => true
-Any.is(1); // => false
-
-Type.is("a string"); // => true
-Type.is(1); // => false
-
-var assert = t.assert;
-
-assert(t.Str.is("a string")); // => ok
-assert(t.Str.is(1)); // => fail!
-
-var x = -2;
-var min = 0;
-// throws "-2 should be greater then 0"
-assert(x > min, "%s should be greater then %s", x, min);
-
-Str("a string"); // => ok
-
-class Point1 {
- x: number;
- y: number;
- constructor(x: number, y: number) {
- this.x = Num(x);
- this.y = Num(y);
- }
-}
-
-var Foo = t.irreducible("Foo", x => {
- return t.Bool(x.hasOwnProperty("bar"));
-});
-
-Foo.is({ bar: "baz" }); // => true
-
-// defines a type representing positive numbers
-var Positive = t.subtype(t.Num, n => {
- return n >= 0;
-}, "Positive");
-
-Positive.is(1); // => true
-Positive.is(-1); // => false
-
-var Country = t.enums({
- IT: "Italy",
- US: "United States"
-}, "Country");
-
-Country.is("IT"); // => true
-Country.is("FR"); // => false
-
-// values will mirror the keys
-Country = t.enums.of("IT US", "Country");
-
-// same as
-
-Country = t.enums(["IT", "US"], "Country");
-
-// same as
-
-Country = t.enums({
- IT: "IT",
- US: "US"
-}, "Country");
-
-var Point = t.struct({
+var noop = function () {};
+var Point = struct({
x: Num,
y: Num
-}, "Point");
-
-// constructor usage, `p` is immutable, new is optional
-var p2 = new Point({ x: 1, y: 2 });
-
-Point.is(p2); // => true
-
-// now p is mutable
-new Point({ x: 1, y: 2 }, true);
-
-Point.extend({ z: Num }, "Point3D");
-
-// multiple inheritance
-var A = struct({});
-var B = struct({});
-var MixinC = {};
-var MixinD = {};
-A.extend([B, MixinC, MixinD]);
-
-var Rectangle = struct({
- width: Num,
- height: Num
});
-Rectangle.prototype.getArea = function() {
- return this.width * this.height;
-};
+describe('update', function () {
+
+ var update = t.update;
+ var Tuple = tuple([Str, Num]);
+ var List = list(Num);
+ var Dict = dict(Str, Num);
+
+ it('should handle $set command', function () {
+ var instance = 1;
+ var actual = update(instance, {$set: 2});
+ eq(actual, 2);
+ var instance2 = [1, 2, 3];
+ actual = update(instance2, {1: {'$set': 4}});
+ eq(instance2, [1, 2, 3]);
+ eq(actual, [1, 4, 3]);
+ });
+
+ it('$set and null value, fix #65', function () {
+ var NullStruct = struct({a: Num, b: maybe(Num)});
+ var instance = new NullStruct({a: 1});
+ var updated = update(instance, {b: {$set: 2}});
+ eq(instance, {a: 1, b: null});
+ eq(updated, {a: 1, b: 2});
+ });
+
+ it('should handle $apply command', function () {
+ var $apply = function (n:any) { return n + 1; };
+ var instance = 1;
+ var actual = update(instance, {$apply: $apply});
+ eq(actual, 2);
+ var instance2 = [1, 2, 3];
+ actual = update(instance2, {1: {'$apply': $apply}});
+ eq(instance2, [1, 2, 3]);
+ eq(actual, [1, 3, 3]);
+ });
+
+ it('should handle $unshift command', function () {
+ var actual = update([1, 2, 3], {'$unshift': [4]});
+ eq(actual, [4, 1, 2, 3]);
+ actual = update([1, 2, 3], {'$unshift': [4, 5]});
+ eq(actual, [4, 5, 1, 2, 3]);
+ actual = update([1, 2, 3], {'$unshift': [[4, 5]]});
+ eq(actual, [[4, 5], 1, 2, 3]);
+ });
+
+ it('should handle $push command', function () {
+ var actual = update([1, 2, 3], {'$push': [4]});
+ eq(actual, [1, 2, 3, 4]);
+ actual = update([1, 2, 3], {'$push': [4, 5]});
+ eq(actual, [1, 2, 3, 4, 5]);
+ actual = update([1, 2, 3], {'$push': [[4, 5]]});
+ eq(actual, [1, 2, 3, [4, 5]]);
+ });
+
+ it('should handle $splice command', function () {
+ var instance = [1, 2, {a: [12, 17, 15]}];
+ var actual = update(instance, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
+ eq(instance, [1, 2, {a: [12, 17, 15]}]);
+ eq(actual, [1, 2, {a: [12, 13, 14, 15]}]);
+ });
+
+ it('should handle $remove command', function () {
+ var instance = {a: 1, b: 2};
+ var actual = update(instance, {'$remove': ['a']});
+ eq(instance, {a: 1, b: 2});
+ eq(actual, {b: 2});
+ });
+
+ it('should handle $swap command', function () {
+ var instance = [1, 2, 3, 4];
+ var actual = update(instance, {'$swap': {from: 1, to: 2}});
+ eq(instance, [1, 2, 3, 4]);
+ eq(actual, [1, 3, 2, 4]);
+ });
+
+ describe('structs', function () {
+
+ var instance = new Point({x: 0, y: 1});
+
+ it('should handle $set command', function () {
+ var updated = update(instance, {x: {$set: 1}});
+ eq(instance, {x: 0, y: 1});
+ eq(updated, {x: 1, y: 1});
+ });
+
+ it('should handle $apply command', function () {
+ var updated = update(instance, {x: {$apply: function (x:any) {
+ return x + 2;
+ }}});
+ eq(instance, {x: 0, y: 1});
+ eq(updated, {x: 2, y: 1});
+ });
+
+ it('should handle $merge command', function () {
+ var updated = update(instance, {'$merge': {x: 2, y: 2}});
+ eq(instance, {x: 0, y: 1});
+ eq(updated, {x: 2, y: 2});
+ var Nested = struct({
+ a: Num,
+ b: struct({
+ c: Num,
+ d: Num,
+ e: Num
+ })
+ });
+ instance = new Nested({a: 1, b: {c: 2, d: 3, e: 4}});
+ updated = update(instance, {b: {'$merge': {c: 5, e: 6}}});
+ eq(instance, {a: 1, b: {c: 2, d: 3, e: 4}});
+ eq(updated, {a: 1, b: {c: 5, d: 3, e: 6}});
+ });
+
+ });
+
+ describe('tuples', function () {
+
+ var instance = Tuple(['a', 1]);
+
+ it('should handle $set command', function () {
+ var updated = update(instance, {0: {$set: 'b'}});
+ eq(updated, ['b', 1]);
+ });
+
+ });
+
+ describe('lists', function () {
+
+ var instance = List([1, 2, 3, 4]);
+
+ it('should handle $set command', function () {
+ var updated = update(instance, {2: {$set: 5}});
+ eq(updated, [1, 2, 5, 4]);
+ });
+
+ it('should handle $splice command', function () {
+ var updated = update(instance, {$splice: [[1, 2, 5, 6]]});
+ eq(updated, [1, 5, 6, 4]);
+ });
+
+ it('should handle $concat command', function () {
+ var updated = update(instance, {$push: [5]});
+ eq(updated, [1, 2, 3, 4, 5]);
+ updated = update(instance, {$push: [5, 6]});
+ eq(updated, [1, 2, 3, 4, 5, 6]);
+ });
+
+ it('should handle $prepend command', function () {
+ var updated = update(instance, {$unshift: [5]});
+ eq(updated, [5, 1, 2, 3, 4]);
+ updated = update(instance, {$unshift: [5, 6]});
+ eq(updated, [5, 6, 1, 2, 3, 4]);
+ });
+
+ it('should handle $swap command', function () {
+ var updated = update(instance, {$swap: {from: 1, to: 2}});
+ eq(updated, [1, 3, 2, 4]);
+ });
+
+ });
+
+ describe('dicts', function () {
+
+ var instance = Dict({a: 1, b: 2});
+
+ it('should handle $set command', function () {
+ var updated = update(instance, {a: {$set: 2}});
+ eq(updated, {a: 2, b: 2});
+ });
+
+ it('should handle $remove command', function () {
+ var updated = update(instance, {$remove: ['a']});
+ eq(updated, {b: 2});
+ });
+
+ });
+
+ describe('memory saving', function () {
+
+ it('should reuse members that are not updated', function () {
+ var Struct = struct({
+ a: Num,
+ b: Str,
+ c: tuple([Num, Num]),
+ });
+ var List = list(Struct);
+ var instance = List([{
+ a: 1,
+ b: 'one',
+ c: [1000, 1000000]
+ },{
+ a: 2,
+ b: 'two',
+ c: [2000, 2000000]
+ }]);
+
+ var updated = update(instance, {
+ 1: {
+ a: {$set: 119}
+ }
+ });
+
+ assert.strictEqual(( updated)[0], ( instance)[0]);
+ assert.notStrictEqual(( updated)[1], ( instance)[1]);
+ assert.strictEqual(( updated)[1].c, ( instance)[1].c);
+ });
+ });
+
+ describe('all together now', function () {
+
+ it('should handle mixed commands', function () {
+ var Struct = struct({
+ a: Num,
+ b: Tuple,
+ c: List,
+ d: Dict
+ });
+ var instance = new Struct({
+ a: 1,
+ b: ['a', 1],
+ c: [1, 2, 3, 4],
+ d: {a: 1, b: 2}
+ });
+ var updated = update(instance, {
+ a: {$set: 1},
+ b: {0: {$set: 'b'}},
+ c: {2: {$set: 5}},
+ d: {$remove: ['a']}
+ });
+ eq(updated, {
+ a: 1,
+ b: ['b', 1],
+ c: [1, 2, 5, 4],
+ d: {b: 2}
+ });
+ });
+
+ it('should handle nested structures', function () {
+ var Struct = struct({
+ a: struct({
+ b: tuple([
+ Str,
+ list(Num)
+ ])
+ })
+ });
+ var instance = new Struct({
+ a: {
+ b: ['a', [1, 2, 3]]
+ }
+ });
+ var updated = update(instance, {
+ a: {b: {1: {2: {$set: 4}}}}
+ });
+ eq(updated, {
+ a: {
+ b: ['a', [1, 2, 4]]
+ }
+ });
+ });
+
+ });
-var Cube = Rectangle.extend({
- thickness: Num
});
-// typeof Cube.prototype.getArea === 'function'
-Cube.prototype.getVolume = function() {
- return this.getArea() * this.thickness;
-};
+//
+// assert
+//
-var Area = tuple([Num, Num]);
+describe('assert', function () {
-// constructor usage, `area` is immutable
-Area([1, 2]);
+ var assert = t.assert;
-var Path = list(Point);
+ it('should nor throw when guard is true', function () {
+ assert(true);
+ });
-// costructor usage, `path` is immutable
-Path([
- { x: 0, y: 0 }, // tcomb hydrates automatically using the `Point` constructor
- { x: 1, y: 1 }
-]);
+ it('should throw a default message', function () {
+ throwsWithMessage(function () {
+ assert(1 === 2);
+ }, 'assert failed');
+ });
-var Tel = dict(Str, Num);
+ it('should throw the specified message', function () {
+ throwsWithMessage(function () {
+ assert(1 === 2, 'my message');
+ }, 'my message');
+ });
-// costructor usage, `tel` is immutable
-Tel({ jack: 4098, sape: 4139 });
+ it('should format the specified message', function () {
+ throwsWithMessage(function () {
+ assert(1 === 2, '%s !== %s', 1, 2);
+ }, '1 !== 2');
+ });
-var ReactKey = union([Str, Num]);
+ it('should handle custom fail behaviour', function () {
+ var fail = t.fail;
+ t.fail = function (message) {
+ try {
+ throw new Error(message);
+ } catch (e) {
+ eq(e.message, 'report error');
+ }
+ };
+ doesNotThrow(function () {
+ assert(1 === 2, 'report error');
+ });
+ t.fail = fail;
+ });
-ReactKey.is("a"); // => true
-ReactKey.is(1); // => true
-ReactKey.is(true); // => false
+});
-ReactKey.dispatch = x => {
- if (Str.is(x)) return Str;
- if (Num.is(x)) return Num;
- return Any;
-};
+//
+// utils
+//
-// now you can do this without a fail
-ReactKey("a");
+describe('format(str, [...])', function () {
-// the value of a radio input where null = no selection
-var Radio = maybe(Str);
+ it('should format strings', function () {
+ eq(format('%s', 'a'), 'a');
+ eq(format('%s', 2), '2');
+ eq(format('%s === %s', 1, 1), '1 === 1');
+ });
-Radio.is("a"); // => true
-Radio.is(null); // => true
-Radio.is(1); // => false
+ it('should format JSON', function () {
+ eq(format('%j', {a: 1}), '{"a":1}');
+ });
-// add takes two `Num`s and returns a `Num`
-var add = func([Num, Num], Num)
- .of((x: number, y: number) => { return x + y; });
+ it('should handle undefined formatters', function () {
+ eq(format('%o', 'a'), '%o a');
+ });
-add("Hello", 2); // Raises error: Invalid `Hello` supplied to `Num`
-add("Hello"); // Raises error: Invalid `Hello` supplied to `Num`
+ it('should handle escaping %', function () {
+ eq(format('%%s'), '%s');
+ });
-add(1, 2); // Returns: 3
-add(1)(2); // Returns: 3
+ it('should not consume an argument with a single %', function () {
+ eq(format('%s%', '100'), '100%');
+ });
-// An `A` takes a `Str` and returns an `Num`
-func(Str, Num);
+ it('should handle less arguments than placeholders', function () {
+ eq(format('%s %s', 'a'), 'a %s');
+ });
-// A `B` takes a `Func` (which takes a `Str` and returns a `Num`) and returns a `Str`.
-func(func(Str, Num), Str);
+ it('should handle more arguments than placeholders', function () {
+ eq(format('%s', 'a', 'b', 'c'), 'a b c');
+ });
-// An `ExcitedStr` is a `Str` containing an exclamation mark
-var ExcitedStr = subtype(Str, s => { return s.indexOf("!") !== -1; }, "ExcitedStr");
+ it('should be extensible', function () {
+ (format).formatters.l = function (x:any) { return x.length; };
+ eq(format('%l', ['a', 'b', 'c']), '3');
+ });
-// An `Exciter` takes a `Str` and returns an `ExcitedStr`
-var Exciter = func(Str, ExcitedStr);
+});
-// A `C` takes an `A`, a `B` and a `Str` and returns a `Num`
-func([A, B, Str], Num);
+describe('mixin(x, y, [overwrite])', function () {
-func(A, B).of(() => {});
+ it('should mix two objects', function () {
+ var o1 = {a: 1};
+ var o2 = {b: 2};
+ var o3 = mixin(o1, o2);
+ ok(o3 === o1);
+ eq(o3.a, 1);
+ eq(o3.b, 2);
+ });
-var simpleQuestionator = Exciter.of((s: string) => { return s + "?"; });
-var simpleExciter = Exciter.of((s: string) => { return s + "!"; });
+ it('should throw if a property already exists', function () {
+ throwsWithMessage(function () {
+ var o1 = {a: 1};
+ var o2 = {a: 2, b: 2};
+ mixin(o1, o2);
+ }, 'Cannot overwrite property a');
+ });
-// Raises error:
-// Invalid `Hello?` supplied to `ExcitedStr`, insert a valid value for the subtype
-simpleQuestionator("Hello");
+ it('should not throw if a property already exists but overwrite = true', function () {
+ var o1 = {a: 1};
+ var o2 = {a: 2, b: 2};
+ var o3 = mixin(o1, o2, true);
+ eq(o3.a, 2);
+ eq(o3.b, 2);
+ });
-// Raises error: Invalid `1` supplied to `Str`
-simpleExciter(1);
+ it('should not mix prototype properties', function () {
+ function F() {}
+ F.prototype.method = noop;
+ var source = new (F)();
+ var target = {};
+ mixin(target, source);
+ eq((target).method, undefined);
+ });
-// Returns: "Hello!"
-simpleExciter("Hello");
+});
-// We can reasonably suggest that add has the following type signature
-// add : Num -> Num -> Num
-add = func([Num, Num], Num)
- .of((x: number, y: number) => { return x + y });
+describe('getFunctionName(f, [defaultName])', function () {
-add("Hello"); // As this raises: "Error: Invalid `Hello` supplied to `Num`"
+ var getFunctionName = t.getFunctionName;
-var add2 = add(2);
-add2(1); // And this returns: 3
+ it('should return the name of a named function', function () {
+ eq(getFunctionName(function myfunc(){}), 'myfunc');
+ });
-func(A, B).is(x);
+ it('should return the value of `displayName` if specified', function () {
+ var f = function myfunc(){};
+ (f).displayName = 'mydisplayname';
+ eq(getFunctionName(f), 'mydisplayname');
+ });
-Exciter.is(simpleExciter); // Returns: true
-Exciter.is(simpleQuestionator); // Returns: true
+ it('should fallback on function arity if nothing is specified', function () {
+ eq(getFunctionName(function (a:any, b:any, c:any) { return a + b + c; }), '');
+ });
-var id = (x: number) => { return x; };
+});
-func([Num, Num], Num).is(func([Num, Num], Num).of(id)); // Returns: true
-func([Num, Num], Num).is(func(Num, Num).of(id)); // Returns: false
+describe('getTypeName(type)', function () {
-var p4 = new Point({x: 1, y: 2});
+ var UnnamedStruct = struct({});
+ var NamedStruct = struct({}, 'NamedStruct');
+ var UnnamedUnion = union([Str, Num]);
+ var NamedUnion = union([Str, Num], 'NamedUnion');
+ var UnnamedMaybe = maybe(Str);
+ var NamedMaybe = maybe(Str, 'NamedMaybe');
+ var UnnamedEnums = enums({a: 'A', b: 'B'});
+ var NamedEnums = enums({}, 'NamedEnums');
+ var UnnamedTuple = tuple([Str, Num]);
+ var NamedTuple = tuple([Str, Num], 'NamedTuple');
+ var UnnamedSubtype = subtype(Str, function notEmpty(x) { return x !== ''; });
+ var NamedSubtype = subtype(Str, function (x) { return x !== ''; }, 'NamedSubtype');
+ var UnnamedList = list(Str);
+ var NamedList = list(Str, 'NamedList');
+ var UnnamedDict = dict(Str, Str);
+ var NamedDict = dict(Str, Str, 'NamedDict');
+ var UnnamedFunc = func(Str, Str);
+ var NamedFunc = func(Str, Str, 'NamedFunc');
-p4 = Point.update(p4, { x: { "$set": 3 } }); // => {x: 3, y: 2}
+ it('should return the name of a named type', function () {
+ eq(getTypeName(NamedStruct), 'NamedStruct');
+ eq(getTypeName(NamedUnion), 'NamedUnion');
+ eq(getTypeName(NamedMaybe), 'NamedMaybe');
+ eq(getTypeName(NamedEnums), 'NamedEnums');
+ eq(getTypeName(NamedTuple), 'NamedTuple');
+ eq(getTypeName(NamedSubtype), 'NamedSubtype');
+ eq(getTypeName(NamedList), 'NamedList');
+ eq(getTypeName(NamedDict), 'NamedDict');
+ eq(getTypeName(NamedFunc), 'NamedFunc');
+ });
-var Type2 = dict(Str, Num);
-var instance = Type2({ a: 1, b: 2 });
-Type2.update(instance, { $remove: ["a"] }); // => {b: 2}
+ it('should return a meaningful name of a unnamed type', function () {
+ eq(getTypeName(UnnamedStruct), '{}');
+ eq(getTypeName(UnnamedUnion), 'Str | Num');
+ eq(getTypeName(UnnamedMaybe), '?Str');
+ eq(getTypeName(UnnamedEnums), '"a" | "b"');
+ eq(getTypeName(UnnamedTuple), '[Str, Num]');
+ eq(getTypeName(UnnamedSubtype), '{Str | notEmpty}');
+ eq(getTypeName(UnnamedList), 'Array');
+ eq(getTypeName(UnnamedDict), '{[key:Str]: Str}');
+ eq(getTypeName(UnnamedFunc), '(Str) => Str');
+ });
-var Type3 = list(Num);
-var instance2 = Type3([1, 2, 3, 4]);
-Type3.update(instance2, { "$swap": { from: 1, to: 2 } }); // => [1, 3, 2, 4]
+});
-t.options.onFail = message => {
- return message;
-};
+//
+// Any
+//
-t.format("Invalid argument `name` = `%s` supplied to `%s`", 1, "MyType");
+describe('Any', function () {
-t.getKind(Str); // => 'irreducible'
-t.getKind(list(Str)); // => 'list'
+ var T = Any;
-t.getFunctionName(t.getKind); // => 'getKind'
-t.getFunctionName(() => { }); // => ''
+ describe('constructor', function () {
-t.getTypeName(Str);
+ it('should behave like identity', function () {
+ eq(Any('a'), 'a');
+ });
-t.mixin({ a: 1 }, { b: 2 }); // => {a: 1, b: 2}
-t.mixin({ a: 1 }, { a: 2 }); // => fail!
+ it('should throw if used with new', function () {
+ throwsWithMessage(function () {
+ /* jshint ignore:start */
+ var x = new (T)();
+ /* jshint ignore:end */
+ }, 'Operator `new` is forbidden for type `Any`');
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ it('should always return true', function () {
+ ok(T.is(null));
+ ok(T.is(undefined));
+ ok(T.is(0));
+ ok(T.is(true));
+ ok(T.is(''));
+ ok(T.is([]));
+ ok(T.is({}));
+ ok(T.is(noop));
+ ok(T.is(/a/));
+ ok(T.is(new RegExp('a')));
+ ok(T.is(new Error()));
+ });
+
+ });
+
+});
+
+//
+// irreducible types
+//
+
+describe('irreducible types constructors', function () {
+
+ [
+ {T: Nil, x: null},
+ {T: Str, x: 'a'},
+ {T: Num, x: 1},
+ {T: Bool, x: true},
+ {T: Arr, x: []},
+ {T: Obj, x: {}},
+ {T: Func, x: noop},
+ {T: Err, x: new Error()},
+ {T: Re, x: /a/},
+ {T: Dat, x: new Date()}
+ ].forEach(function (o) {
+
+ var T = o.T;
+ var x = o.x;
+
+ it('should accept only valid values', function () {
+ eq(T(x), x);
+ });
+
+ it('should throw if used with new', function () {
+ throwsWithMessage(function () {
+ /* jshint ignore:start */
+ var x = new (T) ();
+ /* jshint ignore:end */
+ }, 'Operator `new` is forbidden for type `' + getTypeName(T) + '`');
+ });
+
+ });
+
+});
+
+describe('Nil', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is null or undefined', function () {
+ ok(Nil.is(null));
+ ok(Nil.is(undefined));
+ });
+
+ it('should return false when x is neither null nor undefined', function () {
+ ko(Nil.is(0));
+ ko(Nil.is(true));
+ ko(Nil.is(''));
+ ko(Nil.is([]));
+ ko(Nil.is({}));
+ ko(Nil.is(noop));
+ ko(Nil.is(new Error()));
+ ko(Nil.is(new Date()));
+ ko(Nil.is(/a/));
+ ko(Nil.is(new RegExp('a')));
+ });
+
+ });
+
+});
+
+describe('Bool', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is true or false', function () {
+ ok(Bool.is(true));
+ ok(Bool.is(false));
+ });
+
+ it('should return false when x is neither true nor false', function () {
+ ko(Bool.is(null));
+ ko(Bool.is(undefined));
+ ko(Bool.is(0));
+ ko(Bool.is(''));
+ ko(Bool.is([]));
+ ko(Bool.is({}));
+ ko(Bool.is(noop));
+ ko(Bool.is(/a/));
+ ko(Bool.is(new RegExp('a')));
+ ko(Bool.is(new Error()));
+ ko(Bool.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Num', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is a number', function () {
+ ok(Num.is(0));
+ ok(Num.is(1));
+ /* jshint ignore:start */
+ ko(Num.is(new Number(1)));
+ /* jshint ignore:end */
+ });
+
+ it('should return false when x is not a number', function () {
+ ko(Num.is(NaN));
+ ko(Num.is(Infinity));
+ ko(Num.is(-Infinity));
+ ko(Num.is(null));
+ ko(Num.is(undefined));
+ ko(Num.is(true));
+ ko(Num.is(''));
+ ko(Num.is([]));
+ ko(Num.is({}));
+ ko(Num.is(noop));
+ ko(Num.is(/a/));
+ ko(Num.is(new RegExp('a')));
+ ko(Num.is(new Error()));
+ ko(Num.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Str', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is a string', function () {
+ ok(Str.is(''));
+ ok(Str.is('a'));
+ /* jshint ignore:start */
+ ko(Str.is(new String('a')));
+ /* jshint ignore:end */
+ });
+
+ it('should return false when x is not a string', function () {
+ ko(Str.is(NaN));
+ ko(Str.is(Infinity));
+ ko(Str.is(-Infinity));
+ ko(Str.is(null));
+ ko(Str.is(undefined));
+ ko(Str.is(true));
+ ko(Str.is(1));
+ ko(Str.is([]));
+ ko(Str.is({}));
+ ko(Str.is(noop));
+ ko(Str.is(/a/));
+ ko(Str.is(new RegExp('a')));
+ ko(Str.is(new Error()));
+ ko(Str.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Arr', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an array', function () {
+ ok(Arr.is([]));
+ });
+
+ it('should return false when x is not an array', function () {
+ ko(Arr.is(NaN));
+ ko(Arr.is(Infinity));
+ ko(Arr.is(-Infinity));
+ ko(Arr.is(null));
+ ko(Arr.is(undefined));
+ ko(Arr.is(true));
+ ko(Arr.is(1));
+ ko(Arr.is('a'));
+ ko(Arr.is({}));
+ ko(Arr.is(noop));
+ ko(Arr.is(/a/));
+ ko(Arr.is(new RegExp('a')));
+ ko(Arr.is(new Error()));
+ ko(Arr.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Obj', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an object', function () {
+ function A() {}
+ ok(Obj.is({}));
+ ok(Obj.is(new (A)()));
+ });
+
+ it('should return false when x is not an object', function () {
+ ko(Obj.is(null));
+ ko(Obj.is(undefined));
+ ko(Obj.is(0));
+ ko(Obj.is(''));
+ ko(Obj.is([]));
+ ko(Obj.is(noop));
+ });
+
+ });
+
+});
+
+describe('Func', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is a function', function () {
+ ok(Func.is(noop));
+ /* jshint ignore:start */
+ ok(Func.is(new Function()));
+ /* jshint ignore:end */
+ });
+
+ it('should return false when x is not a function', function () {
+ ko(Func.is(null));
+ ko(Func.is(undefined));
+ ko(Func.is(0));
+ ko(Func.is(''));
+ ko(Func.is([]));
+ /* jshint ignore:start */
+ ko(Func.is(new String('1')));
+ ko(Func.is(new Number(1)));
+ ko(Func.is(new Boolean()));
+ /* jshint ignore:end */
+ ko(Func.is(/a/));
+ ko(Func.is(new RegExp('a')));
+ ko(Func.is(new Error()));
+ ko(Func.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Err', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an error', function () {
+ ok(Err.is(new Error()));
+ });
+
+ it('should return false when x is not an error', function () {
+ ko(Err.is(null));
+ ko(Err.is(undefined));
+ ko(Err.is(0));
+ ko(Err.is(''));
+ ko(Err.is([]));
+ /* jshint ignore:start */
+ ko(Err.is(new String('1')));
+ ko(Err.is(new Number(1)));
+ ko(Err.is(new Boolean()));
+ /* jshint ignore:end */
+ ko(Err.is(/a/));
+ ko(Err.is(new RegExp('a')));
+ ko(Err.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Re', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is a regexp', function () {
+ ok(Re.is(/a/));
+ ok(Re.is(new RegExp('a')));
+ });
+
+ it('should return false when x is not a regexp', function () {
+ ko(Re.is(null));
+ ko(Re.is(undefined));
+ ko(Re.is(0));
+ ko(Re.is(''));
+ ko(Re.is([]));
+ /* jshint ignore:start */
+ ko(Re.is(new String('1')));
+ ko(Re.is(new Number(1)));
+ ko(Re.is(new Boolean()));
+ /* jshint ignore:end */
+ ko(Re.is(new Error()));
+ ko(Re.is(new Date()));
+ });
+
+ });
+
+});
+
+describe('Dat', function () {
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is a Dat', function () {
+ ok(Dat.is(new Date()));
+ });
+
+ it('should return false when x is not a Dat', function () {
+ ko(Dat.is(null));
+ ko(Dat.is(undefined));
+ ko(Dat.is(0));
+ ko(Dat.is(''));
+ ko(Dat.is([]));
+ /* jshint ignore:start */
+ ko(Dat.is(new String('1')));
+ ko(Dat.is(new Number(1)));
+ ko(Dat.is(new Boolean()));
+ /* jshint ignore:end */
+ ko(Dat.is(new Error()));
+ ko(Dat.is(/a/));
+ ko(Dat.is(new RegExp('a')));
+ });
+
+ });
+
+});
+
+//
+// struct
+//
+
+describe('struct', function () {
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (struct)();
+ }, 'Invalid argument `props` = `undefined` supplied to `struct` combinator');
+
+ throwsWithMessage(function () {
+ struct({a: null});
+ }, 'Invalid argument `props` = `[object Object]` supplied to `struct` combinator');
+
+ throwsWithMessage(function () {
+ (struct)({}, 1);
+ }, 'Invalid argument `name` = `1` supplied to `struct` combinator');
+
+ });
+
+ });
+ describe('constructor', function () {
+
+ it('should be idempotent', function () {
+ var T = Point;
+ var p1 = T({x: 0, y: 0});
+ var p2 = T(p1);
+ eq(Object.isFrozen(p1), true);
+ eq(Object.isFrozen(p2), true);
+ eq(p2 === p1, true);
+ });
+
+ it('should accept only valid values', function () {
+ throwsWithMessage(function () {
+ Point(1);
+ }, 'Invalid argument `value` = `1` supplied to struct type `{x: Num, y: Num}`');
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an instance of the struct', function () {
+ var p = new Point({ x: 1, y: 2 });
+ ok(Point.is(p));
+ });
+
+ });
+
+ describe('#update()', function () {
+
+ var Type = struct({name: Str});
+ var instance = new Type({name: 'Giulio'});
+
+ it('should return a new instance', function () {
+ var newInstance = Type.update(instance, {name: {$set: 'Canti'}});
+ ok(Type.is(newInstance));
+ eq( ( instance).name, 'Giulio');
+ eq(( newInstance).name, 'Canti');
+ });
+
+ });
+
+ describe('#extend(props, [name])', function () {
+
+ it('should extend an existing struct', function () {
+ var Point = struct({
+ x: Num,
+ y: Num
+ }, 'Point');
+ var Point3D = Point.extend({z: Num}, 'Point3D');
+ eq(getTypeName(Point3D), 'Point3D');
+ eq((Point3D).meta.props.x, Num);
+ eq((Point3D).meta.props.y, Num);
+ eq((Point3D).meta.props.z, Num);
+ });
+
+ it('should handle an array as argument', function () {
+ var Type = struct({a: Str}, 'Type');
+ var Mixin = [{b: Num, c: Bool}];
+ var NewType = Type.extend(Mixin, 'NewType');
+ eq(getTypeName(NewType), 'NewType');
+ eq((NewType).meta.props.a, Str);
+ eq((NewType).meta.props.b, Num);
+ eq((NewType).meta.props.c, Bool);
+ });
+
+ it('should handle a struct (or list of structs) as argument', function () {
+ var A = struct({a: Str}, 'A');
+ var B = struct({b: Str}, 'B');
+ var C = struct({c: Str}, 'C');
+ var MixinD = {d: Str};
+ var E = A.extend([B, C, MixinD]);
+ eq(E.meta.props, {
+ a: Str,
+ b: Str,
+ c: Str,
+ d: Str
+ });
+ });
+
+ it('should support prototypal inheritance', function () {
+ var Rectangle = struct({
+ w: Num,
+ h: Num
+ }, 'Rectangle');
+ Rectangle.prototype.area = function () {
+ return this.w * this.h;
+ };
+ var Cube = Rectangle.extend({
+ l: Num
+ });
+ Cube.prototype.volume = function () {
+ return this.area() * this.l;
+ };
+
+ assert('function' === typeof Rectangle.prototype.area);
+ assert('function' === typeof Cube.prototype.area);
+ assert(undefined === Rectangle.prototype.volume);
+ assert('function' === typeof Cube.prototype.volume);
+ assert(Cube.prototype.constructor === Cube);
+
+ var c = new Cube({w:2, h:2, l:2});
+ eq((c).volume(), 8);
+ });
+
+ });
+
+});
+
+//
+// enums
+//
+
+describe('enums', function () {
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (enums)();
+ }, 'Invalid argument `map` = `undefined` supplied to `enums` combinator');
+
+ throwsWithMessage(function () {
+ (enums)({}, 1);
+ }, 'Invalid argument `name` = `1` supplied to `enums` combinator');
+
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ var T = enums({a: 0}, 'T');
+
+ it('should throw if used with new', function () {
+ throwsWithMessage(function () {
+ /* jshint ignore:start */
+ var x = new (T)('a');
+ /* jshint ignore:end */
+ }, 'Operator `new` is forbidden for type `T`');
+ });
+
+ it('should accept only valid values', function () {
+ eq((T)('a'), 'a');
+ throwsWithMessage(function () {
+ (T)('b');
+ }, 'Invalid argument `value` = `b` supplied to enums type `T`, expected one of ["a"]');
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ var Direction = enums({
+ North: 0,
+ East: 1,
+ South: 2,
+ West: 3,
+ 1: 'North-East',
+ 2.5: 'South-East'
+ });
+
+ it('should return true when x is an instance of the enum', function () {
+ ok(Direction.is('North'));
+ ok(Direction.is(1));
+ ok(Direction.is('1'));
+ ok(Direction.is(2.5));
+ });
+
+ it('should return false when x is not an instance of the enum', function () {
+ ko(Direction.is('North-East'));
+ ko(Direction.is(2));
+ });
+
+ });
+
+ describe('#of(keys)', function () {
+
+ it('should return an enum', function () {
+ var Size = (enums).of(['large', 'small', 1, 10.9]); ///!!!
+ ok(Size.meta.map.large === 'large');
+ ok(Size.meta.map.small === 'small');
+ ok(Size.meta.map['1'] === 1);
+ ok(Size.meta.map[10.9] === 10.9);
+ });
+
+ it('should handle a string', function () {
+ var Size = (enums).of('large small 10');
+ ok(Size.meta.map.large === 'large');
+ ok(Size.meta.map.small === 'small');
+ ok(Size.meta.map['10'] === '10');
+ ok(Size.meta.map[10] === '10');
+ });
+
+ });
+
+});
+
+//
+// union
+//
+
+describe('union', function () {
+
+ var Circle = struct({
+ center: Point,
+ radius: Num
+ }, 'Circle');
+
+ var Rectangle = struct({
+ a: Point,
+ b: Point
+ });
+
+ var Shape = union([Circle, Rectangle], 'Shape');
+
+ Shape.dispatch = function (values) {
+ assert(Obj.is(values));
+ return values.hasOwnProperty('center') ?
+ Circle :
+ Rectangle;
+ };
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (union)();
+ }, 'Invalid argument `types` = `undefined` supplied to `union` combinator');
+
+ throwsWithMessage(function () {
+ union([]);
+ }, 'Invalid argument `types` = `` supplied to `union` combinator, provide at least two types');
+
+ throwsWithMessage(function () {
+ union([Circle]);
+ }, 'Invalid argument `types` = `Circle` supplied to `union` combinator, provide at least two types');
+
+ throwsWithMessage(function () {
+ (union)([Circle, Point], 1);
+ }, 'Invalid argument `name` = `1` supplied to `union` combinator');
+
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ it('should throw when dispatch() is not implemented', function () {
+ throwsWithMessage(function () {
+ var T = union([Str, Num], 'T');
+ T.dispatch = null;
+ T(1);
+ }, 'Unimplemented `dispatch()` function for union type `T`');
+ });
+
+ it('should have a default dispatch() implementation', function () {
+ var T = union([Str, Num], 'T');
+ eq(T(1), 1);
+ });
+
+ it('should throw when dispatch() does not return a type', function () {
+ throwsWithMessage(function () {
+ var T = union([Str, Num], 'T');
+ T(true);
+ }, 'The `dispatch()` function of union type `T` returns no type constructor');
+ });
+
+ it('should build instances when dispatch() is implemented', function () {
+ var circle = Shape({center: {x: 0, y: 0}, radius: 10});
+ ok(Circle.is(circle));
+ });
+
+ it('should throw if used with new and union types are not instantiables with new', function () {
+ throwsWithMessage(function () {
+ var T = union([Str, Num], 'T');
+ T.dispatch = function () { return Str; };
+ /* jshint ignore:start */
+ var x = new T('a');
+ /* jshint ignore:end */
+ }, 'Operator `new` is forbidden for type `T`');
+ });
+
+ it('should not throw if used with new and union types are instantiables with new', function () {
+ doesNotThrow(function () {
+ Shape({center: {x: 0, y: 0}, radius: 10});
+ });
+ });
+
+ it('should be idempotent', function () {
+ var p1 = Shape({center: {x: 0, y: 0}, radius: 10});
+ var p2 = Shape(p1);
+ eq(Object.isFrozen(p1), true);
+ eq(Object.isFrozen(p2), true);
+ eq(p2 === p1, true);
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an instance of the union', function () {
+ var p = new Circle({center: { x: 0, y: 0 }, radius: 10});
+ ok(Shape.is(p));
+ });
+
+ });
+
+});
+
+//
+// maybe
+//
+
+describe('maybe', function () {
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (maybe)();
+ }, 'Invalid argument `type` = `undefined` supplied to `maybe` combinator');
+
+ throwsWithMessage(function () {
+ (maybe)(Point, 1);
+ }, 'Invalid argument `name` = `1` supplied to `maybe` combinator');
+
+ });
+
+ it('should be idempotent', function () {
+ var MaybeStr = maybe(Str);
+ ok(maybe(MaybeStr) === MaybeStr);
+ });
+
+ it('should be noop with Any', function () {
+ ok(maybe(Any) === Any);
+ });
+
+ it('should be noop with Nil', function () {
+ ok((maybe)(Nil) === Nil);
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ it('should throw if used with new', function () {
+ throwsWithMessage(function () {
+ /* jshint ignore:start */
+ var T = maybe(Str, 'T');
+ var x = new (T)();
+ /* jshint ignore:end */
+ }, 'Operator `new` is forbidden for type `T`');
+ });
+
+ it('should coerce values', function () {
+ var T = maybe(Point);
+ eq(T(null), null);
+ eq(T(undefined), null);
+ ok(Point.is(T({x: 0, y: 0})));
+ });
+
+ it('should be idempotent', function () {
+ var T = maybe(Point);
+ var p1 = T({x: 0, y: 0});
+ var p2 = T(p1);
+ eq(Object.isFrozen(p1), true);
+ eq(Object.isFrozen(p2), true);
+ eq(p2 === p1, true);
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an instance of the maybe', function () {
+ var Radio = maybe(Str);
+ ok(Radio.is('a'));
+ ok(Radio.is(null));
+ ok(Radio.is(undefined));
+ });
+
+ });
+
+});
+
+//
+// tuple
+//
+
+describe('tuple', function () {
+
+ var Area = tuple([Num, Num], 'Area');
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (tuple)();
+ }, 'Invalid argument `types` = `undefined` supplied to `tuple` combinator');
+
+ throwsWithMessage(function () {
+ (tuple)([Point, Point], 1);
+ }, 'Invalid argument `name` = `1` supplied to `tuple` combinator');
+
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ var S = struct({}, 'S');
+ var T = tuple([S, S], 'T');
+
+ it('should coerce values', function () {
+ var t = T([{}, {}]);
+ ok(S.is(( t)[0]));
+ ok(S.is(( t)[1]));
+ });
+
+ it('should accept only valid values', function () {
+
+ throwsWithMessage(function () {
+ T(1);
+ }, 'Invalid argument `value` = `1` supplied to tuple type `T`, expected an `Arr` of length `2`');
+
+ throwsWithMessage(function () {
+ T([1, 1]);
+ }, 'Invalid argument `value` = `1` supplied to struct type `S`');
+
+ });
+
+ it('should be idempotent', function () {
+ var T = tuple([Str, Num]);
+ var p1 = T(['a', 1]);
+ var p2 = T(p1);
+ eq(Object.isFrozen(p1), true);
+ eq(Object.isFrozen(p2), true);
+ eq(p2 === p1, true);
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ it('should return true when x is an instance of the tuple', function () {
+ ok(Area.is([1, 2]));
+ });
+
+ it('should return false when x is not an instance of the tuple', function () {
+ ko(Area.is([1]));
+ ko(Area.is([1, 2, 3]));
+ ko(Area.is([1, 'a']));
+ });
+
+ it('should not depend on `this`', function () {
+ ok([[1, 2]].every(Area.is));
+ });
+
+ });
+
+ describe('#update()', function () {
+
+ var Type = tuple([Str, Num]);
+ var instance = Type(['a', 1]);
+
+ it('should return a new instance', function () {
+ var newInstance = Type.update(instance, {0: {$set: 'b'}});
+ assert(Type.is(newInstance));
+ assert(( instance)[0] === 'a');
+ assert(( newInstance)[0] === 'b');
+ });
+
+ });
+
+});
+
+//
+// list
+//
+
+describe('list', function () {
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (list)();
+ }, 'Invalid argument `type` = `undefined` supplied to `list` combinator');
+
+ throwsWithMessage(function () {
+ (list)(Point, 1);
+ }, 'Invalid argument `name` = `1` supplied to `list` combinator');
+
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ var S = struct({}, 'S');
+ var T = list(S, 'T');
+
+ it('should coerce values', function () {
+ var t = T([{}]);
+ ok(S.is(( t)[0]));
+ });
+
+ it('should accept only valid values', function () {
+
+ throwsWithMessage(function () {
+ T(1);
+ }, 'Invalid argument `value` = `1` supplied to list type `T`');
+
+ throwsWithMessage(function () {
+ T([1]);
+ }, 'Invalid argument `value` = `1` supplied to struct type `S`');
+
+ });
+
+ it('should be idempotent', function () {
+ var T = list(Num);
+ var p1 = T([1, 2]);
+ var p2 = T(p1);
+ eq(Object.isFrozen(p1), true);
+ eq(Object.isFrozen(p2), true);
+ eq(p2 === p1, true);
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ var Path = list(Point);
+ var p1 = new Point({x: 0, y: 0});
+ var p2 = new Point({x: 1, y: 1});
+
+ it('should return true when x is a list', function () {
+ ok(Path.is([p1, p2]));
+ });
+
+ it('should not depend on `this`', function () {
+ ok([[p1, p2]].every(Path.is));
+ });
+
+ });
+
+ describe('#update()', function () {
+
+ var Type = list(Str);
+ var instance = Type(['a', 'b']);
+
+ it('should return a new instance', function () {
+ var newInstance = Type.update(instance, {'$push': ['c']});
+ assert(Type.is(newInstance));
+ assert((instance).length === 2);
+ assert((newInstance).length === 3);
+ });
+
+ });
+
+});
+
+//
+// subtype
+//
+
+describe('subtype', function () {
+
+ var True = function () { return true; };
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (subtype)();
+ }, 'Invalid argument `type` = `undefined` supplied to `subtype` combinator');
+
+ throwsWithMessage(function () {
+ subtype(Point, null);
+ }, 'Invalid argument `predicate` = `null` supplied to `subtype` combinator');
+
+ throwsWithMessage(function () {
+ (subtype)(Point, True, 1);
+ }, 'Invalid argument `name` = `1` supplied to `subtype` combinator');
+
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ it('should throw if used with new and a type that is not instantiable with new', function () {
+ throwsWithMessage(function () {
+ /* jshint ignore:start */
+ var T = subtype(Str, function () { return true; }, 'T');
+ var x = new( T)();
+ /* jshint ignore:end */
+ }, 'Operator `new` is forbidden for type `T`');
+ });
+
+ it('should coerce values', function () {
+ var T = subtype(Point, function () { return true; });
+ var p = T({x: 0, y: 0});
+ ok(Point.is(p));
+ });
+
+ it('should accept only valid values', function () {
+ var predicate = function (p:any) { return p.x > 0; };
+ var T = subtype(Point, predicate, 'T');
+ throwsWithMessage(function () {
+ T({x: 0, y: 0});
+ }, 'Invalid argument `value` = `[object Object]` supplied to subtype type `T`');
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ var Positive = subtype(Num, function (n) {
+ return n >= 0;
+ });
+
+ it('should return true when x is a subtype', function () {
+ ok(Positive.is(1));
+ });
+
+ it('should return false when x is not a subtype', function () {
+ ko(Positive.is(-1));
+ });
+
+ });
+
+ describe('#update()', function () {
+
+ var Type = subtype(Str, function (s) { return s.length > 2; });
+ var instance = Type('abc');
+
+ it('should return a new instance', function () {
+ var newInstance = Type.update(instance, {'$set': 'bca'});
+ assert(Type.is(newInstance));
+ eq(newInstance, 'bca');
+ });
+
+ });
+
+});
+
+//
+// dict
+//
+
+describe('dict', function () {
+
+ describe('combinator', function () {
+
+ it('should throw if used with wrong arguments', function () {
+
+ throwsWithMessage(function () {
+ (dict)();
+ }, 'Invalid argument `domain` = `undefined` supplied to `dict` combinator');
+
+ throwsWithMessage(function () {
+ (dict)(Str);
+ }, 'Invalid argument `codomain` = `undefined` supplied to `dict` combinator');
+
+ throwsWithMessage(function () {
+ (dict)(Str, Point, 1);
+ }, 'Invalid argument `name` = `1` supplied to `dict` combinator');
+
+ });
+
+ });
+
+ describe('constructor', function () {
+
+ var S = struct({}, 'S');
+ var Domain = subtype(Str, function (x) {
+ return x !== 'forbidden';
+ }, 'Domain');
+ var T = dict(Domain, S, 'T');
+
+ it('should coerce values', function () {
+ var t = T({a: {}});
+ ok(S.is((t).a));
+ });
+
+ it('should accept only valid values', function () {
+
+ throwsWithMessage(function () {
+ T(1);
+ }, 'Invalid argument `value` = `1` supplied to dict type `T`');
+
+ throwsWithMessage(function () {
+ T({a: 1});
+ }, 'Invalid argument `value` = `1` supplied to struct type `S`');
+
+ throwsWithMessage(function () {
+ T({forbidden: {}});
+ }, 'Invalid argument `value` = `forbidden` supplied to subtype type `Domain`');
+
+ });
+
+ it('should be idempotent', function () {
+ var T = dict(Str, Str);
+ var p1 = T({a: 'a', b: 'b'});
+ var p2 = T(p1);
+ eq(Object.isFrozen(p1), true);
+ eq(Object.isFrozen(p2), true);
+ eq(p2 === p1, true);
+ });
+
+ });
+
+ describe('#is(x)', function () {
+
+ var T = dict(Str, Point);
+ var p1 = new Point({x: 0, y: 0});
+ var p2 = new Point({x: 1, y: 1});
+
+ it('should return true when x is a list', function () {
+ ok(T.is({a: p1, b: p2}));
+ });
+
+ it('should not depend on `this`', function () {
+ ok([{a: p1, b: p2}].every(T.is));
+ });
+
+ });
+
+ describe('#update()', function () {
+
+ var Type = dict(Str, Str);
+ var instance = Type({p1: 'a', p2: 'b'});
+
+ it('should return a new instance', function () {
+ var newInstance = Type.update(instance, {p2: {$set: 'c'}});
+ ok(Type.is(newInstance));
+ eq((instance).p2, 'b');
+ eq((newInstance).p2, 'c');
+ });
+
+ });
+
+});
+
+//
+// func
+//
+
+describe('func', function () {
+
+ it('should handle a no types', function () {
+ var T = func([], Str);
+ eq(T.meta.domain.length, 0);
+ var getGreeting = T.of(function () { return 'Hi'; });
+ eq(getGreeting(), 'Hi');
+ });
+
+ it('should handle a single type', function () {
+ var T = func(Num, Num);
+ eq(T.meta.domain.length, 1);
+ ok(T.meta.domain[0] === Num);
+ });
+
+ it('should automatically instrument a function', function () {
+ var T = func(Num, Num);
+ var f = function () { return 'hi'; };
+ ok(T.is(T(f)));
+ });
+
+ describe('of', function () {
+
+ it('should check the arguments', function () {
+
+ var T = func([Num, Num], Num);
+ var sum = T.of(function (a:any, b:any) {
+ return a + b;
+ });
+ eq(sum(1, 2), 3);
+
+ throwsWithMessage(function () {
+ sum(1, 2, 3);
+ }, 'Invalid argument `value` = `1,2,3` supplied to tuple type `[Num, Num]`, expected an `Arr` of length `2`');
+
+ throwsWithMessage(function () {
+ sum('a', 2);
+ }, 'Invalid argument `value` = `a` supplied to irreducible type `Num`');
+
+ });
+
+ it('should check the return value', function () {
+
+ var T = func([Num, Num], Num);
+ var sum = T.of(function () {
+ return 'a';
+ });
+
+ throwsWithMessage(function () {
+ sum(1, 2);
+ }, 'Invalid argument `value` = `a` supplied to irreducible type `Num`');
+
+ });
+
+ it('should preserve `this`', function () {
+ var o = {name: 'giulio'};
+ (o).getTypeName = func([], Str).of(function () {
+ return this.name;
+ });
+ eq((o).getTypeName(), 'giulio');
+ });
+
+ it('should handle function types', function () {
+ var A = func([Str], Str);
+ var B = func([Str, A], Str);
+
+ var f = A.of(function (s:any) {
+ return s + '!';
+ });
+ var g = B.of(function (str:any, strAction:any) {
+ return strAction(str);
+ });
+
+ eq(g('hello', f), 'hello!');
+ });
+
+ it('should be idempotent', function () {
+ var f = function (s:any) { return s; };
+ var g = func([Str], Str).of(f);
+ var h = func([Str], Str).of(g);
+ ok(h === g);
+ });
+
+ });
+
+ describe('currying', function () {
+
+ it('should curry functions', function () {
+ var Type = func([Num, Num, Num], Num);
+ var sum = Type.of(function (a:any, b:any, c:any) {
+ return a + b + c;
+ });
+ eq(sum(1, 2, 3), 6);
+ eq(sum(1, 2)(3), 6);
+ eq(sum(1)(2, 3), 6);
+ eq(sum(1)(2)(3), 6);
+
+ // important: the curried function must be of the correct type
+ var CurriedType = func([Num, Num], Num);
+ var sum1 = sum(1);
+ eq(sum1(2, 3), 6);
+ eq(sum1(2)(3), 6);
+ ok(CurriedType.is(sum1));
+ });
+
+ it('should throw if partial arguments are wrong', function () {
+
+ var T = func([Num, Num], Num);
+ var sum = T.of(function (a:any, b:any) {
+ return a + b;
+ });
+
+ throwsWithMessage(function () {
+ sum('a');
+ }, 'Invalid argument `value` = `a` supplied to irreducible type `Num`');
+
+ throwsWithMessage(function () {
+ var sum1 = sum(1);
+ sum1('a');
+ }, 'Invalid argument `value` = `a` supplied to irreducible type `Num`');
+
+ });
+
+ });
+
+});
diff --git a/tcomb/tcomb.d.ts b/tcomb/tcomb.d.ts
index 3c9197d867..c189a6a0f5 100644
--- a/tcomb/tcomb.d.ts
+++ b/tcomb/tcomb.d.ts
@@ -1,420 +1,425 @@
-// Type definitions for tcomb v0.4
+// Type definitions for tcomb v1.0.3
// Project: http://gcanti.github.io/tcomb/guide/index.html
-// Definitions by: Jed Mao
+// Definitions by: Hans Windhoff
// Definitions: https://github.com/borisyankov/DefinitelyTyped
-declare module tcomb {
+// Original Definitions by: Jed Mao
+declare module TComb {
+ export interface tcomb {
+ format: (format: string, ...values: any[]) => string;
+ getFunctionName: (fn: Function) => string;
+ getTypeName: (type: TCombBase) => string;
+ mixin: (target: {}, source: {}, overwrite?: boolean) => any;
+ slice: typeof Array.prototype.slice;
+ shallowCopy: (x: TCombBase) => TCombBase;
+ update: (instance: any, spec: {} ) => TCombBase;
+ assert: (condition: boolean, message?: string, ...values: any[]) => void;
+ fail: (message?: string) => void;
+ Any: Any_Static;
+ Nil: Str_Static;
+ Str: Str_Static;
+ Num: Num_Static;
+ Bool: Bool_Static;
+ Arr: Arr_Static;
+ Obj: Obj_Static;
- export var options: {
- onFail: (message: string) => void;
- };
+ Func: Func_Static;
+ func: { (domain: TCombBase[], codomain: TCombBase, name?: string) : Func_Static;
+ (domain: TCombBase, codomain: TCombBase, name?: string) : Func_Static;
+ }
+ Err: Err_Static;
+ Re: Re_Static;
+ Dat: Dat_Static;
+ Type: Type_Static;
+ irreducible: (name: string, is: TypePredicate) => TCombBase;
+ struct: (props: Object, name?: string) => Struct_Static;
- /**
- * Like util.format in Node.
- */
- export function format(format: string, ...values: any[]): string;
- export function getKind(type: T): string;
- /**
- * Returns a function's name or displayName if specified; otherwise,
- * fallbacks on '>'.
- */
- export function getFunctionName(fn: Function): string;
- export function getTypeName(type: T): string;
- /**
- * Safe version of mixin, properties can be overwritten.
- */
- export function mixin(target: {}, source: {}, overwrite?: boolean): any;
- export var slice: typeof Array.prototype.slice;
- export function shallowCopy(x: T): T;
- export function update(instance: any, spec: {}): T;
- /**
- * If an assert fails the debugger kicks in so you can inspect the stack
- * and quickly find out what's wrong.
- * @param message - Useful for debugging. Formatted with values like util.format in Node.
- * @param values - Sequentially inserted into the message.
- */
- export function assert(condition: boolean, message?: string, ...values: any[]): void;
- export function fail(message?: string): void;
+ Union: Union_Static;
+ Maybe: Maybe_Static;
- interface T {
- meta: {
+ enums(map: Object, name?: string): TCombBase;
+ union(types: TCombBase[], name?: string): Union_Static;
+ maybe(type: TCombBase, name?: string): Maybe_Static;
+
+ Tuple: Tuple_Static;
+ tuple:(types: TCombBase[], name?: string)=> Tuple_Static;
+
+ Subtype: Subtype_Static;
+
+ List: List_Static;
+ list:(type: TCombBase, name?: string)=> List_Static;
+
+ Dict: Dict_Static;
+ dict:(domain: TCombBase, codomain: TCombBase, name?: string)=> Dict_Static;
+
+ subtype(type: TCombBase, predicate: TypePredicate, name?: string): Subtype_Static;
+
+ }
+
+
+
+
+ export interface TCombBase {
+ meta: {
/**
* The type kind, equal to "irreducible" for irreducible types.
*/
- kind: string;
+ kind: string;
/**
* The type name.
*/
- name: string;
- };
- displayName: string;
- is(value: any): boolean;
- update(instance: any, spec: {}): T;
- }
+ name: string;
+ };
+ displayName: string;
+ is(value: any): boolean;
+ update(instance: any, spec: {}): TCombBase;
+ }
- interface TypePredicate {
- (x: any): Bool_Instance;
- }
+ export interface TypePredicate {
+ (x: any): Bool_Instance;
+ }
- interface Any_Instance {
- }
+ export interface Any_Instance {
+ }
- interface Any_Static extends T {
- new (value: any): Any_Instance;
- (value: any): Any_Instance;
- }
+ export interface Any_Static extends TCombBase {
- export var Any: Any_Static;
+ new (value: any): Any_Instance;
+ (value: any): Any_Instance;
+ }
- interface Nil_Instance {
- }
- interface Nil_Static extends T {
- new (value: any): Nil_Instance;
- (value: any): Nil_Instance;
- }
- export var Nil: Str_Static;
+ export interface Nil_Instance {
+ }
- interface Str_Instance extends String {
- }
+ export interface Nil_Static extends TCombBase {
+ new (value: any): Nil_Instance;
+ (value: any): Nil_Instance;
+ }
- interface Str_Static extends T {
- new (value: string): Str_Instance;
- (value: string): Str_Instance;
- meta: {
+
+
+ export interface Str_Instance extends String {
+ }
+
+ export interface Str_Static extends TCombBase {
+ new (value: string): Str_Instance;
+ (value: string): Str_Instance;
+ meta: {
/**
* The type kind, equal to "irreducible" for irreducible types.
*/
- kind: string;
+ kind: string;
/**
* The type name.
*/
- name: string;
+ name: string;
/**
* The type predicate.
*/
- is: TypePredicate;
- };
- }
+ is: TypePredicate;
+ };
+ }
- export var Str: Str_Static;
- interface Num_Instance extends Number {
- }
- interface Num_Static extends T {
- new (value: number): Num_Instance;
- (value: number): Num_Instance;
- }
+ export interface Num_Instance extends Number {
+ }
- export var Num: Num_Static;
+ export interface Num_Static extends TCombBase {
+ new (value: number): Num_Instance;
+ (value: number): Num_Instance;
+ }
- interface Bool_Instance extends Boolean {
- }
- interface Bool_Static extends T {
- new (value: boolean): Bool_Instance;
- (value: boolean): Bool_Instance;
- }
- export var Bool: Bool_Static;
+ export interface Bool_Instance extends Boolean {
+ }
- interface Arr_Instance extends Array {
- }
+ export interface Bool_Static extends TCombBase {
+ new (value: boolean): Bool_Instance;
+ (value: boolean): Bool_Instance;
+ }
- interface Arr_Static extends T {
- new (value: any[]): Arr_Instance;
- (value: any[]): Arr_Instance;
- }
- export var Arr: Arr_Static;
- interface Obj_Instance extends Object {
- }
+ export interface Arr_Instance extends Array {
+ }
- interface Obj_Static extends T {
- new (value: Object): Obj_Instance;
- (value: Object): Obj_Instance;
- }
+ export interface Arr_Static extends TCombBase {
+ new (value: any[]): Arr_Instance;
+ (value: any[]): Arr_Instance;
+ }
- export var Obj: Obj_Static;
- interface Func_Instance extends Function {
- }
- interface Func_Static extends T {
- new (value: Function): Func_Instance;
- (value: Function): Func_Instance;
- }
+ export interface Obj_Instance extends Object {
+ }
- export var Func: Func_Static;
+ export interface Obj_Static extends TCombBase {
- interface Err_Instance extends Error {
- }
+ new (value: Object): Obj_Instance;
+ (value: Object): Obj_Instance;
+ }
- interface Err_Static extends T {
- new (value: Error): Err_Instance;
- (value: Error): Err_Instance;
- }
- export var Err: Err_Static;
- interface Re_Instance extends RegExp {
- }
+ export interface Func_Instance extends Function {
+ }
- interface Re_Static extends T {
- new (value: RegExp): Re_Instance;
- (value: RegExp): Re_Instance;
- }
+ export interface Func_Static extends TCombBase {
+ new (value: Function): Func_Instance;
+ (value: Function): Func_Instance;
+ }
- export var Re: Re_Static;
- interface Dat_Instance extends Date {
- }
+ export interface Err_Instance extends Error {
+ }
- interface Dat_Static extends T {
- new (value: Date): Dat_Instance;
- (value: Date): Dat_Instance;
- }
+ export interface Err_Static extends TCombBase {
+ new (value: Error): Err_Instance;
+ (value: Error): Err_Instance;
+ }
- export var Dat: Dat_Static;
- interface Type_Instance {
- }
+ export interface Re_Instance extends RegExp {
+ }
+
+ export interface Re_Static extends TCombBase {
+ new (value: RegExp): Re_Instance;
+ (value: RegExp): Re_Instance;
+ }
+
+
+ export interface Dat_Instance extends Date {
+ }
+
+ export interface Dat_Static extends TCombBase {
+ new (value: Date): Dat_Instance;
+ (value: Date): Dat_Instance;
+ }
+
+ export interface Type_Instance {
+ }
+
+ export interface Type_Static extends TCombBase {
+ new (value: any): Type_Instance;
+ (value: any): Type_Instance;
+ }
- interface Type_Static extends T {
- new (value: any): Type_Instance;
- (value: any): Type_Instance;
- }
- export var Type: Type_Static;
/**
* @param name - The type name.
* @param is - A predicate.
*/
- export function irreducible(name: string, is: TypePredicate): T;
+
/**
* @param props - A hash whose keys are the field names and the values are the fields types.
* @param name - Useful for debugging purposes.
*/
- export function struct(props: Object, name?: string): typeof Struct;
- export interface Struct_Static extends T {
- new (value: any, mutable?: boolean): Struct_Instance;
- (value: any, mutable?: boolean): Struct_Instance;
- meta: {
- kind: string;
- name: string;
- props: any[];
- };
- /**
- * @param mixins - Contains the new props.
- * @param name - Useful for debugging purposes.
- */
- extend(mixins: Object, name?: string): Struct_Static;
- /**
- * @param mixins - Contains the new props.
- * @param name - Useful for debugging purposes.
- */
- extend(mixins: Struct_Static, name?: string): Struct_Static;
- /**
- * @param mixins - Contains the new props.
- * @param name - Useful for debugging purposes.
- */
- extend(mixins: Object[], name?: string): Struct_Static;
- /**
- * @param mixins - Contains the new props.
- * @param name - Useful for debugging purposes.
- */
- extend(mixins: Struct_Static[], name?: string): Struct_Static;
- }
- interface Struct_Instance {
- }
+ export interface Struct_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Struct_Instance;
+ (value: any, mutable?: boolean): Struct_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ props: any[];
+ };
+ /**
+ * @param mixins - Contains the new props.
+ * @param name - Useful for debugging purposes.
+ */
+ extend(mixins: Object, name?: string): Struct_Static;
+ /**
+ * @param mixins - Contains the new props.
+ * @param name - Useful for debugging purposes.
+ */
+ extend(mixins: Struct_Static, name?: string): Struct_Static;
+ /**
+ * @param mixins - Contains the new props.
+ * @param name - Useful for debugging purposes.
+ */
+ extend(mixins: Object[], name?: string): Struct_Static;
+ /**
+ * @param mixins - Contains the new props.
+ * @param name - Useful for debugging purposes.
+ */
+ extend(mixins: Struct_Static[], name?: string): Struct_Static;
+ }
- export var Struct: Struct_Static;
+ interface Struct_Instance {
+ }
/**
* @param map - A hash whose keys are the enums (values are free).
* @param name - Useful for debugging purposes.
*/
- export function enums(map: Object, name?: string): T;
- export module enums {
+
+ export module enums {
/**
* @param keys - Array of enums.
* @param name - Useful for debugging purposes.
*/
- export function of(keys: string[], name?: string): T;
+ export function of(keys: string[], name?: string): TCombBase;
/**
* @param keys - String of enums separated by spaces.
* @param name - Useful for debugging purposes.
*/
- export function of(keys: string, name?: string): T;
- }
+ export function of(keys: string, name?: string): TCombBase;
+ }
/**
* @param name - Useful for debugging purposes.
*/
- export function union(types: T[], name?: string): Union_Static;
- interface Union_Static extends T {
- new (value: any, mutable?: boolean): Union_Instance;
- (value: any, mutable?: boolean): Union_Instance;
- meta: {
- kind: string;
- name: string;
- types: T[];
- };
- dispatch(x: any): T;
- }
+ export interface Union_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Union_Instance;
+ (value: any, mutable?: boolean): Union_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ types: TCombBase[];
+ };
+ dispatch(x: any): TCombBase;
+ }
- interface Union_Instance {
- }
+ export interface Union_Instance {
+ }
- export var Union: Union_Static;
/**
* @param type - The wrapped type.
* @param name - Useful for debugging purposes.
*/
- export function maybe(type: T, name?: string): Maybe_Static;
- export interface Maybe_Static extends T {
- new (value: any, mutable?: boolean): Maybe_Instance;
- (value: any, mutable?: boolean): Maybe_Instance;
- meta: {
- kind: string;
- name: string;
- typee: T;
- };
- }
- interface Maybe_Instance {
- }
- export var Maybe: Maybe_Static;
+ export interface Maybe_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Maybe_Instance;
+ (value: any, mutable?: boolean): Maybe_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ typee: TCombBase;
+ };
+ }
+
+ interface Maybe_Instance {
+ }
+
/**
* @param name - Useful for debugging purposes.
*/
- export function tuple(types: T[], name?: string): Tuple_Static;
- interface Tuple_Static extends T {
- new (value: any, mutable?: boolean): Tuple_Instance;
- (value: any, mutable?: boolean): Tuple_Instance;
- meta: {
- kind: string;
- name: string;
- types: T[];
- };
- }
+ interface Tuple_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Tuple_Instance;
+ (value: any, mutable?: boolean): Tuple_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ types: TCombBase[];
+ };
+ }
- interface Tuple_Instance {
- }
+ interface Tuple_Instance {
+ }
- export var Tuple: Tuple_Static;
-
/**
* Combines old types into a new one.
* @param type - A type already defined.
* @param name - Useful for debugging purposes.
*/
- export function subtype(type: T, predicate: TypePredicate, name?: string): typeof Subtype;
- interface Subtype_Static extends T {
- new (value: any, mutable?: boolean): Subtype_Instance;
- (value: any, mutable?: boolean): Subtype_Instance;
- meta: {
- kind: string;
- name: string;
- type: T;
- predicate: TypePredicate;
- };
- }
- interface Subtype_Instance {
- }
+ export interface Subtype_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Subtype_Instance;
+ (value: any, mutable?: boolean): Subtype_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ type: TCombBase;
+ predicate: TypePredicate;
+ };
+ }
- export var Subtype: Subtype_Static;
+ interface Subtype_Instance {
+ }
/**
* @param type - The type of list items.
* @param name - Useful for debugging purposes.
*/
- export function list(type: T, name?: string): List_Static;
+ export function list(type: TCombBase, name?: string): List_Static;
- interface List_Static extends T {
- new (value: any, mutable?: boolean): List_Instance;
- (value: any, mutable?: boolean): List_Instance;
- meta: {
- kind: string;
- name: string;
- 'type': T;
- };
- }
+ interface List_Static extends TCombBase {
+ new (value: any, mutable?: boolean): List_Instance;
+ (value: any, mutable?: boolean): List_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ 'type': TCombBase;
+ };
+ }
- interface List_Instance {
- }
-
- export var List: List_Static;
+ interface List_Instance {
+ }
/**
* @param domain - The type of keys.
* @param codomain - The type of values.
* @param name - Useful for debugging purposes.
*/
- export function dict(domain: T, codomain: T, name?: string): Dict_Static;
- interface Dict_Static extends T {
- new (value: any, mutable?: boolean): Dict_Instance;
- (value: any, mutable?: boolean): Dict_Instance;
- meta: {
- kind: string;
- name: string;
- domain: T;
- codomain: T;
- };
- }
- interface Dict_Instance {
- }
+ interface Dict_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Dict_Instance;
+ (value: any, mutable?: boolean): Dict_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ domain: TCombBase;
+ codomain: TCombBase;
+ };
+ }
- export var Dict: Dict_Static;
+ interface Dict_Instance {
+ }
/**
* @param type - The type of the function's argument.
* @param codomain - The type of the function's return value.
* @param name - Useful for debugging purposes.
*/
- export function func(domain: T, codomain: T, name?: string): Func_Static;
/**
* @param type - The list of types of the function's arguments.
* @param codomain - The type of the function's return value.
* @param name - Useful for debugging purposes.
*/
- export function func(domain: T[], codomain: T, name?: string): Func_Static;
- interface Func_Static extends T {
- new (value: any, mutable?: boolean): Func_Instance;
- (value: any, mutable?: boolean): Func_Instance;
- meta: {
- kind: string;
- name: string;
- domain: any;
- codomain: T;
- };
- of(fn: Function): Function;
- }
+ interface Func_Static extends TCombBase {
+ new (value: any, mutable?: boolean): Func_Instance;
+ (value: any, mutable?: boolean): Func_Instance;
+ meta: {
+ kind: string;
+ name: string;
+ domain: any;
+ codomain: TCombBase;
+ };
+ of(fn: Function): Function;
+ }
- interface Func_Instance {
- }
-
- export var Func: Func_Static;
+ interface Func_Instance {
+ }
}
+declare var t: TComb.tcomb;
+
declare module "tcomb" {
- export = tcomb;
+ export = t;
}