Runtime type-checking for JavaScript.
npm install typify> Runtime type-checking.




Install the module with: npm install typify
``javascript
// Browser
//
// Node
var typify = require("typify");
/*
* sum function takes either two numbers or two strings as a parameter,
* and returns a number or a string respectively.
*/
var sum = typify("sum :: a : number|string => a -> a -> a", function (a, b) {
return a + b;
});
/*
* toArray function takes either an array of numbers or a single number,toArray :: a : , (array a)|a -> array a
* and returns an array of numbers.
*
* We could write a more general, polymorphic function with type signature
, where * means _any type_.
*
Unfortunately any type is seriously any.id :: a : , a -> a
Types as typify* understands them, are more like Java's interfaces or Haskell's typeclasses.
* Of course, we can iterate through them all, but we cannot deduce the most principal type (because it doesn't exist).
So eg. function signature behaves similarly to id :: -> , which isn't strict enough.
*/
var toNumberArray = typify("toNumberArray :: (array number)|number -> array number", function (a) {
return Array.isArray(a) ? a : [a];
});
/*
* myParseInt takes a string and an optional number (radix) and returns a number.
*/
var myParseInt = typify("myParseInt :: string -> number? -> number", function (n, radix) {
return parseInt(n, radix || 10)
});
/*
* foo takes at least one number parameter and returns a number.`
*/
var foo = typify("foo :: number -> number.. -> number", function (a) {
return a + arguments.length;
});
- typify(functionSpec, fun) - decorate function with run-time type checktypify.create()
- - create new typify environmenttypify.type(typename, checkFun)
- - add new type with user-supplied existence checktypify.record(typename, recordspec)
- - add new record typetypify.alias(typename, typespec)
- - give name to the compound typetypify.mutual(typespecs)
- - define multiple (possibly mutually recursive) types at oncetypify.instance(name, cls)
- - add new instance typetypify.check(typename, value) -> bool
- - check membership of value in the type. check is autoCurried
Checkable means, that given an object you can check whether an object is or isn't of the particular type.
For example number is checkable type, given any object you can tell if it's a number.
`javascript`
typify.check('number', 1); // => true
typify.check('number', 'foobar'); // => false
You could use typify.assert for type assertions:
`javascriptTypeError
typify.check('number', 'foo'); // will throw exception`
There are few predefined checkable types:
- numberinteger
- nat
- : non-negative integerpositive
- _x_nonnegative
- _x_finite
- _x_string
- boolean
- date
- regexp
- function
- , fnarray
- _a_map
- _a_tuple
- _a_ _b_...null
- , undefined, infinity, ninfinity, nan, true and false
#### Formal syntax of checkable type declaration:
- checkable type σ ::= σ_or
- σ_or ::= σ_and (| σ_and)*&
- σ_and ::= σ_poly ( σ_poly)*?
- σ_poly ::= typename σ_opt+ | σ_opt
- σ_opt = σ_term | σ_term {
- σ_record ::= } | { σ_pair (, σ_pair)* }:
- σ_pair ::= identifier σ_term
- σ_term ::= | α | literal | typename* | ( σ_alt )
- type variable α ::= identifier
- literal ::= /\d+/ | /"[^"]"/ | /'[^']'/ | true | false | null | undefined | nan | infinity | ninfinity
- identifier, typename ::= /[a-zA-Z_][a-zA-Z0-9_]*/
Function types are difficult to check. Given a function object, only you can tell, it's a function object.
To be more precise, you can decorate your function with function type signature to verify parameters' and result's types, but the check will occur only when function is executed ie. run-time.
`javascript
var add = typify("add :: number -> number -> number", function (a, b) {
return a + b;
});
console.log(add(1, 2)); // ok
console.log(add("foo", "bar")); // throws TypeError
`
#### Formal syntax of function type declaration:
- function type λ ::= ν μ | ν Γ (σ ->)* ρ σ->
- action μ ::= τ:
- context Γ ::= α Σ (, α : Σ)* => | ε|
- typeset Σ ::= σ_poly ( σ_poly)*...
- rest parameters ρ ::= σ -> | ... -> | ε::
- function name ν ::= identifier | ε
New types can be added with typify.type method:
`javascript`
typify.type("char", function(n) {
return typeof n === "string" && n.length === 1;
});
Note: opaque type checks should return true,
other truthy values will be considered errorneous in later versions.
You can give names to (recursive) compound types with typify.alias:`javascript`
typify.alias("numstr", "number|string"); // numbers or strings
typify.alias("rarray", "array rarray"); // arrays of itself, eg [[[[[[]]]]]
For mutually recursive types use typify.mutual:`javascript`
typify.mutual({
"foo": "list bar",
"bar": "list foo",
});
Also you can define record types with typify.record:
`javascript`
typify.record("person", {
name: "string",
age: "number",
});
Record types may be recursive:
`javascript`
typ.record("bst", {
left: "bst?",
right: "bst?",
});
If you prefer instanceof, there is typify.instance helper in place:`javascript`
function Foo() {}
typ.instance("Foo", Foo);
typ.check("Foo", new Foo());
If you don't want to use global type database, you can create your own instance of typify:
`js
// In browser
var myTypify = typify.create();
// or alternatively, using "let-binding":
(function (typify) {
// use typify as it would be global
}(typify.create()));
// In node
var typify = require("typify").create();
`
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using npm test command.
- 0.2.9 Closed records
- typify.record(name, def, closed)date
- 0.2.8
- Change and regexp checks to work in multiframe environments #34typify.assert
- Fix typo in README.md #35
- Update dependencies
- 0.2.7
- Use make
- 0.2.6
- Updated dependencies
- 0.2.5
- typify.type
- Added note about opaque type checks ()arguments
- 0.2.4
- built-in typeany
- built-in type. Like * but not optionalfn
- typified most of functions
- 0.2.3
- shorthand for the function typetypify.wrap
- to typify modulestypify.adt
- istanbul code covarage as part of the test suite
- helper for specifying abstract data types -like structuresinfinity
- , ninfinity and nan literalstypify.type
- unified implementation of , typify.alias and typify.record`.
- The latter two will be deprecated in 0.3.0 and removed in 0.4.0
- 0.2.2
- mutually recursive types
- instanceof types
- 0.2.1
- anonymous record types
- tuple, numeric types
- mocha test-suite
- major code refactor
- 0.2.0
- Recursive record types
- Recursive aliases
- Intersection types
- Hygiene type environments
- 0.1.1
- Record type
- Fixed typos in README.md
- 0.1.0 Initial release
Copyright (c) 2013 Oleg Grenrus. Licensed under the BSD3 license.
- rho-contracts
- ducktype
- type-check
- Racket - Contracts for higher-order functions
- Typed Clojure
- The Ruby Type Checker