Share your Programming Language Jam submissions here!

← Back to all posts
ClojureTypeScript - Statically Typed ClojureScript
oyvindsabo (6)

Motivation

As a front-end developer, some of my favorite alternatives to vanilla JavaScript are TypeScript and ClojureScript. TypeScript helps you avoid runtime errors by providing static type checking, while ClojureScript enforces a more functional programming style, which results in code which is less spaghetti-esque and easier to test. However, for large production apps, I find it difficult to justify sacrificing TypeScript's static type checking, just to be able to use ClojureScript. In order to save front-end developers from having to consider making such compromises, I @oyvindsabo and my sister @KarolineSabo (our team name is teamsabo, by the way) decided to create ClojureTypeScript, a statically typed ClojureScript.

There have been previous attempts at creating static type checking for Clojure, for instance Typed Clojure (https://typedclojure.org/). We did, however, not find the transition from Clojure to Typed Clojure as intuitive as we found the transition from JavaScript to TypeScript, so there might be room for improvement. With ClojureTypeScript, we have approached the challenge by focusing on simplicity, keeping the syntax close to regular Clojure syntax and not introducing the countless senseless abbreviations which the Clojure community seems very fond of.

Some simple examples

In regular Clojure, a sum function could be written like this:

(fn [a b] (+ a b))
=> [Function]

For all we know, this function might be called with string parameters at runtime, which is not unlikely, considering that many developers trying ClojureScript are used to JavaScript, where adding strings together is okay.

In ClojureTypeScript, the developer is forced to declare the input types of functions, like this.

(fn [a number, b number]
    (+ a b))
=> [Function]

Even without calling the function, runtime errors will be discovered:

(fn [a string, b string]
    (+ a b))
=> TypeError: All arguments passed to + must be of type number

Let's look at a Hello, world function:

(fn [name string]
    (str "Hello, " name "!"))
=> [Function]

Next, let's apply the function:

((fn [name string]
     (str "Hello, " name "!")) "world")
=> Hello, world!

How far did we get?

We implemented an evaluator function which is able to evaluate a subset of Clojure, supporting most of the data structures, as well as quite a few functions from the core library. Type Checking currently only works for primitive types like strings, numbers and booleans, and not for composite types like vectors, sets, maps, lists, etc. Proper typing of functions from the core library is also limited to those dealing with primitive values. It is worth mentioning that static type checking was implemented just a few hours before submitting the project, so while it works for some basic use cases, it's still very much a work in progress.

For instance, the following does not throw a type error:

((fn [name string]
     (str "Hello, " name "!")) 5)

Ouch!

Test it

For this jam, we implemented ClojureTypeScript as an evaluator function in Node.js. Some sample code is evaluated and printed here:
https://repl.it/@teamsabo/ClojureTypeScript#index.js Simply click the link and press the run button once the repl shows up.

For a more interactive experience, we have also made the interpreter available here (the interpreter is the only functionality on this website that works:p):
https://clojuretypescript.org/

Future plans

Clojure has a lot of data structures which JavaScript doesn't. We would like to simplify the language to improve interoperability with JavaScript, and remove complexity which is currently there simply for the sake of imitating Clojure, and which cannot easily be utilized in JavaScript anyways. This could, for instance involve replacing concepts like lists, collections, vectors, sequences etc. with arrays, or completely remove the concept of keywords. We have also been toying with the idea of making it possible to write JSX in ClojureTypeScript, combining the best (or worst?) of everything the front-end world has to offer.

Commentshotnewtop
chrisaycock (24)

Looks like you got reinstated! And our comments were deleted.