intro.js | |
---|---|
Contracts.js is a JavaScript library that allows you to express and enforce complex run-time assertions on JavaScript code. You can write contracts for just about anything in JavaScript including functions (both first-order, higher-order, and dependent), objects, and arrays. | |
To get an idea of how it works, consider this increment function
which simply adds | var inc = function(x) { return x + 1; }; |
Calling | inc(4); // ==> 5 |
For example if we call it with a string type coercion gives
us | inc("hello"); // ==> "hello1" |
So let's see how contracts can help us. | |
The contracts library provides three important functions here:
So this call to | inc = guard(
fun(Num, Num), // a function contract
function(x) { return x + 1; }); // the function to guard |
When we call the guarded function with a number everything works just like normal. | inc(4); // ==> 5 |
But when we call it with a string, the contract fails and we get a nice error message informing us of our mistake:
This lets us know which contract failed ( | inc("hello"); // fails contract! |
We can also apply contracts to higher-order functions. | var hoFun = guard(
fun(fun(Num, Bool), Num),
function(f) {
if( f(42) ) {
return 42;
} else {
return -1;
}
}); |
If the client client passes a function that doesn't pass its
contract, we will fail pointing blame on the client of | hoFun(function(n) { return "foo"; }); |
There is also a combinator for objects. | guard(
object({ a: Str, b: Num}),
{ a: "foo", b: 42 }); |
Along with arrays. Here the first two elements of
the array must be a | guard(
arr([Str, Num, ___(Bool)]),
["foo", 42, false, true, true, false, true]); |
You can also write your own flat contracts using
the | var Even = check(function(val) {
return (val % 2) === 0;
}, "Even"); |
The | var Num = check(function(val) {
return typeof(val) === "number";
}, "Number"); |
You can also express dependent function contracts (where the result of calling a function depends on its arguments). | guard(
fun(Num, function(argument) {
return check(function(result) {
return result > argument;
});
}),
function(n) { return n + 1; });
|