Automatic Type-checking for JavaScript Functions! TypeJS is intented to enhance functional programming JavaScript libraries by adding Haskell-style type definition to functions.
Lets construct a peculiar Add
function
var Add = Type ('Num -> Num -> Int', function (a, b) {
return a + b;
});
Add
takes two Num
s and returns an Int
, since Num
is any number in general but Int
is more strict, this Add
function will only be work if the two numbers given sum to a whole number.
Add(1, 2) //3
Add(1.3, 3.7) //5
Add(2, 2.2) //TypeError: Incorrect output type, expected Int, received Num
Add(2, '3') //TypeError: Incorrect input type, expected Num, received String
Lets modify Add
s type signature a little and add a variable type a
. Type variables have to be A SINGLE LOWERCASE LETTER!!!
var Add = Type ('Num -> a -> a', function (a, b) {
return a + b;
});
The variable type will be infered on the first use of the function.
Add (1, '2') //"12"
Add (1, 2) //TypeError: Incorrect input type, expected String, received Int
Int
s will always be infered as Num
s because in JS there is no way to diferentiate 3.0
from 3
.
List types are compound types and are defined as in Haskell like [a]
. Variable types within lists are infered as you would expect.
var sumReduce = Type ('[a] -> a', function (l) {
return l.reduce( function(a,b) {return a + b;} );
});
a
will first be infered from the list and will be expected as the output type.
sumReduce (['1','2','3']) //"123"
sumReduce ([1,2,3]) //TypeError: Incorrect input type, expected [String], received [Int]
Any number of list nests like [[[a]]]
will work. However, the type definition for the list will be based on its first element, type consistency withing the list will never be supported. For example, [1,'2']
is of type [Int]
while ['2',1]
is of type [String]
.
If a function is incorrectly typed it won't work, even in the first use.
var tellSum = Type ('a -> a -> a', function (num1, num2) {
return "The sum is " + (num1 + num2);
});
tellSum (1,2) //TypeError: Incorrect output type, expected Int, received String
You can create a new typed function for any existing untyped function with the setType() method added to Function.prototype
g = f.setType ('a -> a -> a');
2 | Int |
2.0 | Int |
2.1 | Num |
"2" | String |
[2,3] | [Int] |
[[1,2],[3,4]] | [[Int]] |
- Add the rest of JavaScript types (easy)
- Add type() method to Function.prototype you can access a functions type (relatively easy)
- Support type definition for functions that take functions such as
(a -> b) -> a -> b
(the previous point helps but remains not easy) - Make the return function a curried function that checks the types of the arguments as you add them (currently you can curry the typed function, but types will only be checked when the functions is actually excecuted.
Typing a function has the extra cost of checking the type of all the arguments and output, don't use this in performance critical applications.