$ lein new org.my-domain/my-project
$ cd my-project
14 January 2021
Ambrose Bonnaire-Sergeant
Welcome to Typed Clojure!
Typed Clojure is a library that adds static type checking to Clojure. If you’re an experienced Clojure programmer, you can install it using your favourite tool at these coordinates.
If you’re just starting out, please install Leiningen to try it out. Create a new project in a terminal:
$ lein new org.my-domain/my-project
$ cd my-project
Now change the generated project.clj
file to include the Typed Clojure checker (the latest version can be found here).
(defproject org.my-domain/my-project "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.11.1"]
;; annotation macros like t/ann
[org.typedclojure/typed.clj.runtime "1.1.5"]]
:profiles {:dev {:dependencies [;; the full type checker, only needed at dev-time
[org.typedclojure/typed.clj.checker "1.1.5"]]}}
:repl-options {:init-ns org.my-domain.my-project})
Typed Clojure requires type annotations to check your code. Let’s create a simple function and annotate it.
(ns org.my-domain.my-project
(:require [typed.clojure :as t]))
(t/ann welcome-string [t/Str :-> t/Str])
(defn welcome-string [a-name]
(str "Welcome to " a-name "!"))
(welcome-string "Typed Clojure")
;=> "Welcome to Typed Clojure!"
Now, we can check the namespace. Start a REPL and call check-ns to type check the current namespace.
$ lein repl
Clojure 1.11.1
org.my-domain.my-project=> (t/check-ns-clj)
Start checking org.my-domain.my-project
Checked org.my-domain.my-project in 32.836713 msecs
:ok
Leave your REPL open---we’re going to add a type error to the file and see what happens when we recheck the namespace.
(ns org.my-domain.my-project
(:require [typed.clojure :as t]))
(t/ann welcome-string [t/Str :-> t/Str])
(defn welcome-string [a-name]
(str "Welcome, " a-name))
(welcome-string nil)
Save the file and call check-ns-clj again.
org.my-domain.my-project=> (t/check-ns-clj)
Start checking org.my-domain.my-project
Type Error (file:/Users/ambrose/Projects/typedclojure.org/example-projects/my-project/src/org/my_domain/my_project.clj:10:1)
Function welcome-string could not be applied to arguments:
Domains:
t/Str
Arguments:
nil
Ranges:
t/Str
in:
(welcome-string nil)
Execution error (ExceptionInfo) at clojure.core.typed.errors/print-errors! (errors.cljc:274).
Type Checker: Found 1 error
In Typed Clojure, nil
is not a String
. In most cases, nil
must be specified explicitly---so let’s do that here.
(t/ann welcome-string [(t/U nil t/Str) :-> t/Str])
By the way, use doc-clj to find out more about the namespace-qualified types. Let’s see what U
and Str
mean.
org.my-domain.my-project=> (t/doc-clj t/U)
Special type: typed.clojure/U
U represents a union of types
Forms: [(U type*)]
nil
org.my-domain.my-project=> (t/doc-clj t/Str)
Type alias typed.clojure/Str
String
Metadata:
{:doc "A string", :forms '[Str], :file "typed/ann/clojure.cljc"}
nil
Ok, now since welcome-string
allows nil
, it should type check again (don’t forget to save the file after updating the annotation!).
org.my-domain.my-project=> (t/check-ns-clj)
Start checking org.my-domain.my-project
Checked org.my-domain.my-project in 32.831593 msecs
:ok
Typed Clojure is not extensively documented yet, and lacks tutorials. Currently development is focussed on improving error messages and type inference.
For more hints, I suggest browsing the core.typed wiki, as Typed Clojure is almost a superset of core.typed.
For more specific guidance, open an issue on typedclojure and your question will be answered.