Comparing version 0.0.3 to 0.0.4
{ | ||
"name": "tcomb", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "JavaScript types and combinators", | ||
@@ -5,0 +5,0 @@ "main": "tcomb.js", |
@@ -5,14 +5,22 @@ # tcomb | ||
## Why? | ||
*Why*. tcomb is a library which allows you to **check the types** of JavaScript values at runtime with a **simple syntax**. It is great for checking external input, for testing and for adding safety to your internal code. Bonus points: | ||
tcomb is a library which allows you to check the types of JavaScript values at runtime with a simple syntax. It is great for checking external input, for testing and for adding safety to your internal code. Bonus points: | ||
- easy debugging | ||
- encode/decode of your domain objects to/from JSON for free | ||
- instances are immutables by default | ||
- **instances are immutables** by default | ||
## How | ||
*How*. This library provides several type combinators and a built-in `assert` function you can use. When an **assertion fails this library starts the debugger** so you can inspect the stack and quickly find out what's wrong. The debugger starts only once after the first failed assert. | ||
This library provides several type combinators and a built-in `assert` function you can use. When an assertion fails in the browser this function starts the debugger so you can inspect the stack and find what's wrong. The debugger starts only once after the first failed assert. | ||
*What*. You can define and check: | ||
- JavaScript native types | ||
- structs (i.e. classes) | ||
- unions | ||
- maybe | ||
- enums | ||
- tuples | ||
- subtypes | ||
- lists | ||
- function types (experimental) | ||
## Quick example | ||
@@ -25,3 +33,3 @@ | ||
description: maybe(Str), // an OPTIONAL string (can be `null`) | ||
homepage: Url, // a SUBTYPE string representing a URL | ||
homepage: Url, // a SUBTYPE of string representing an URL | ||
shippings: list(Shipping), // a LIST of shipping methods | ||
@@ -52,2 +60,3 @@ category: Category, // a string in [Audio, Video] (ENUM) | ||
// get an immutable instance | ||
var ipod = new Product({ | ||
@@ -76,34 +85,19 @@ name: 'iPod', | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<title>tcomb setup</title> | ||
<!--[if lt IE 9]> | ||
<script src="shims/json2.js"></script> | ||
<script src="shims/es5-shim.min.js"></script> | ||
<script src="shims/es5-sham.min.js"></script> | ||
<script src="shims/html5shiv.min.js"></script> | ||
<![endif]--> | ||
<script type="text/javascript" src="tcomb.js"></script> | ||
</head> | ||
<body> | ||
<script type="text/javascript"> | ||
console.log(t); | ||
</script> | ||
</body> | ||
</html> | ||
This library uses a few ES5 methods | ||
## Requirements | ||
- Array#forEach() | ||
- Array#map() | ||
- Array#some() | ||
- Array#every() | ||
- Object#keys() | ||
Some ES5 methods | ||
you can use `es5-shim` to support old browsers | ||
Array#forEach() | ||
Array#map() | ||
Array#some() | ||
Array#every() | ||
Object#freeze() | ||
Object#keys() | ||
<!--[if lt IE 9]> | ||
<script src="es5-shim.min.js"></script> | ||
<![endif]--> | ||
<script type="text/javascript" src="tcomb.js"></script> | ||
<script type="text/javascript"> | ||
console.log(t); | ||
</script> | ||
@@ -116,3 +110,3 @@ ## Tests | ||
on the project root. | ||
in the project root. | ||
@@ -147,2 +141,3 @@ ## What's a type? | ||
Str.is('a'); // => true | ||
Nil.is(undefined); // => true | ||
Nil.is(0); // => false | ||
@@ -196,3 +191,3 @@ | ||
Returns an instance with changed props, without modify the original. | ||
Returns an instance with changed props, without modifying the original. | ||
@@ -225,3 +220,3 @@ Point.update(p, {x: 3}); // => new Point({x: 3, y: 2}) | ||
// in order to use Shape as constructor `dispatch(values) -> Type` | ||
// in order to use Shape as a constructor the function `dispatch(values) -> Type` | ||
// must be implemented | ||
@@ -249,3 +244,3 @@ Shape.dispatch = function (values) { | ||
Shape.is(new Circle([p, 10])); // => true | ||
Shape.is(new Circle({center: p, radius: 10})); // => true | ||
@@ -384,2 +379,13 @@ ### maybe(type, [name]) | ||
### func(Arguments, f, [Return], [name]) | ||
Defines a function where the `arguments` and the return value are checked. | ||
var sum = func(tuple([Num, Num]), function (a, b) { | ||
return a + b; | ||
}, Num); | ||
sum(1, 2); // => 3 | ||
sum(1, 'a'); // => fail! | ||
**Useful methods** | ||
@@ -386,0 +392,0 @@ |
46
tcomb.js
@@ -0,1 +1,6 @@ | ||
// tcomb.js 0.0.4 | ||
// https://github.com/gcanti/tcomb | ||
// (c) 2014 Giulio Canti | ||
// tcomb.js may be freely distributed under the MIT license. | ||
(function (root, factory) { | ||
@@ -34,3 +39,3 @@ if (typeof define === 'function' && define.amd) { | ||
function freeze(obj_or_arr, unless) { | ||
if (unless !== true) { | ||
if (unless !== true && Object.freeze) { | ||
Object.freeze(obj_or_arr); | ||
@@ -54,3 +59,3 @@ } | ||
// -------------------------------------------------------------- | ||
// Manipolazione degli array | ||
// array manipulation | ||
// -------------------------------------------------------------- | ||
@@ -413,2 +418,36 @@ | ||
// -------------------------------------------------------------- | ||
// func (experimental) | ||
// -------------------------------------------------------------- | ||
var func = function (Arguments, f, Return, name) { | ||
function func() { | ||
var args = Array.prototype.slice.call(arguments); | ||
if (args.length < f.length) args.length = f.length; // handle optional arguments | ||
args = Arguments.is(args) ? args : new Arguments(args); | ||
var r = f.apply(this, new Arguments(args)); | ||
if (Return) { | ||
r = Return.is(r) ? r : new Return(r); | ||
} | ||
return r; | ||
} | ||
func.is = function (x) { return x === func; }; | ||
func.meta = { | ||
kind: 'func', | ||
Arguments: Arguments, | ||
f: f, | ||
Return: Return, | ||
name: name | ||
}; | ||
return func; | ||
}; | ||
return { | ||
@@ -441,4 +480,5 @@ fail: fail, | ||
subtype: subtype, | ||
list: list | ||
list: list, | ||
func: func | ||
}; | ||
})); |
var assert = require('assert'); | ||
var ok = function (x) { | ||
assert.strictEqual(true, x); | ||
}; | ||
var ko = function (x) { | ||
assert.ok(!x); | ||
}; | ||
var t = require('../tcomb'); | ||
var t = require('../tcomb'); | ||
var Nil = t.Nil; | ||
@@ -17,6 +11,26 @@ var Bool = t.Bool; | ||
var Func = t.Func; | ||
var Err = t.Err; | ||
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 func = t.func; | ||
// | ||
// setup | ||
// | ||
var ok = function (x) { assert.strictEqual(true, x); }; | ||
var ko = function (x) { assert.strictEqual(false, x); }; | ||
var throws = assert.throws; | ||
// structs | ||
var Point = struct({ | ||
x: Num, | ||
y: Num | ||
}, 'Point'); | ||
// enums | ||
var Direction = enums({ | ||
@@ -29,7 +43,3 @@ North: 0, | ||
var Point = struct({ | ||
x: Num, | ||
y: Num | ||
}, 'Point'); | ||
// unions | ||
var Circle = struct({ | ||
@@ -47,2 +57,18 @@ center: Point, | ||
Shape.dispatch = function (values) { | ||
assert(Obj.is(values)); | ||
return values.hasOwnProperty('center') ? | ||
Circle : | ||
Rectangle; | ||
}; | ||
// tuples | ||
var Numbers = tuple([Num, Num]); | ||
// funcs | ||
var sum = func(tuple([Num, Num]), function (a, b) { | ||
return a + b; | ||
}, Num); | ||
// | ||
@@ -210,3 +236,3 @@ // basic types specs | ||
it('should return true when x belongs to the struct', function() { | ||
it('should return true when x is an instance of the struct', function() { | ||
var p = new Point({ x: 1, y: 2 }); | ||
@@ -221,6 +247,6 @@ ok(Point.is(p)); | ||
describe('#is(x)', function(){ | ||
it('should return true when x belongs to the enum', function() { | ||
it('should return true when x is an instance of the enum', function() { | ||
ok(Direction.is('North')); | ||
}); | ||
it("should return false when x don't belongs to the enum", function() { | ||
it("should return false when x is not an instance of the enum", function() { | ||
ko(Direction.is('North-East')); | ||
@@ -233,3 +259,3 @@ }); | ||
describe('#is(x)', function(){ | ||
it('should return true when x belongs to the enum', 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}); | ||
@@ -239,4 +265,77 @@ ok(Shape.is(p)); | ||
}); | ||
describe('Shape constructor', function(){ | ||
it('should be used to buils instances', function() { | ||
}); | ||
}); | ||
}); | ||
describe('tuple', function(){ | ||
describe('#is(x)', function(){ | ||
it('should return true when x is an instance of the tuple', function() { | ||
ok(Numbers.is([1, 2])); | ||
}); | ||
it("should return false when x is not an instance of the tuple", function() { | ||
ko(Numbers.is([1])); | ||
ko(Numbers.is([1, 2, 3])); | ||
ko(Numbers.is([1, 'a'])); | ||
}); | ||
}); | ||
}); | ||
describe('func', function(){ | ||
describe('#is(x)', function(){ | ||
it('should return true when x is the func', function() { | ||
ok(sum.is(sum)); | ||
ok(sum(1, 2) === 3); | ||
}); | ||
it("should return false when x is not the func", function() { | ||
ko(sum.is(function () {})); | ||
}); | ||
it("should throw with wrong arguments", function() { | ||
throws(function () { | ||
sum(1, 'a'); | ||
}); | ||
}); | ||
it("should throw with wrong return", function() { | ||
var bad = func(tuple([Num, Num]), function (a, b) { | ||
return a + String(b); | ||
}, Num); | ||
throws(function () { | ||
bad(1, 2); | ||
}); | ||
}); | ||
it("Return should be optional", function() { | ||
var bad = func(tuple([Num, Num]), function (a, b) { | ||
return a + String(b); | ||
}); | ||
ok(bad(1, 2) === '12'); | ||
}); | ||
it("should handle optional arguments", function() { | ||
var sum3 = func(tuple([Num, Num, maybe(Num)]), function (a, b, c) { | ||
return a + b + (c || 0); | ||
}, Num); | ||
ok(sum3(1, 2, 3) === 6); | ||
ok(sum3(1, 2) === 3); | ||
}); | ||
}); | ||
}); | ||
describe('generics', function(){ | ||
// generic Either A B | ||
var Either = function (A, B) { | ||
return subtype(tuple([maybe(A), maybe(B)]), function (x) { | ||
return Nil.is(x[0]) !== Nil.is(x[1]); | ||
}); | ||
}; | ||
// node.js style callback | ||
var CallbackArguments = Either(Err, Obj); | ||
it('should return true when x is an instance of CallbackArguments', function() { | ||
ok(CallbackArguments.is([null, {}])); | ||
ok(CallbackArguments.is([new Error(), null])); | ||
}); | ||
it('should return false when x is not an instance of CallbackArguments', function() { | ||
ko(CallbackArguments.is([null, null])); | ||
}); | ||
}); | ||
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
679
481
34347
6