Typescript Like Intellisense for Clojure Functions With Malli

To some, it might come as a surprise that you can type Clojure functions and get static type-checking in your editor to warn you about invalid arguments, etc. This is not a feature of the language itself, it is possible via amazing open-source projects CLJ Kondo and Malli.
Similarly to typing Javascript code in Typescript, we can use separate type declaration files to instruct the TS compiler and linter. In Clojure, we can generate clj-kondo type configurations for our library or import these from library authors and enhance the developer experience.
In Malli, typing is similar to TS.
(ns core
(:require [malli.core :as m]
[malli.dev :as dev]))
(defn add [x y]
(+ x y))
(m/=> add [:=>
[:cat :int :int]
:int])
;; start the instrumentation ~ type checking
(dev/start!)
Which generates the following type definitions in the clj-kondo cache that is picked up by the editor integration to provide type hints in your editor.
{:linters
{:unresolved-symbol {:exclude [(malli.core/=>)]},
:type-mismatch
{:namespaces
{core
{add {:arities {2 {:args [:int :int], :ret :int}}}}}}}}
The type definition is fairly close to the TS ones
(m/=> add [:=> ;; type is a function
[:cat :int :int] ;; there's two arguments of type int
:int ;; the function returns an int
])
type add = (Number, Number) => Number;
When we have the instrumentation turned on
(add "2" 1) ;; evaluating this would result in following
-- Schema Error ------------------------------------------------
Invalid function arguments:
["2" 1]
Function Var:
core/add
Input Schema:
[:cat :int :int]
Errors:
{:in [0],
:message "should be an integer",
:path [0],
:schema :int,
:value "2"}
More information:
https://cljdoc.org/d/metosin/malli/CURRENT/doc/function-schemas
This can also be seen in the editor even before evaluating the code.
This week I was working on a small bug on how Malli generates CLJ Kondo type definitions and I thought it'd be a good moment to share some of the basics I picked up on while doing it. I haven't missed the types from TS in a long time but now I know how to configure these when needed.
Thanks for reading, I hope you found this useful.
Subscribe to my newsletter
Read articles from Toni Väisänen directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Toni Väisänen
Toni Väisänen
Software engineer @ Metosin Ltd Need help with a project, contact: first.last@metosin.com As a 𝐜𝐨𝐧𝐬𝐮𝐥𝐭𝐚𝐧𝐭, I help clients find technical solutions to their business problems and facilitate communication between the stakeholders and the technical team. As a 𝐟𝐮𝐥𝐥-𝐬𝐭𝐚𝐜𝐤 𝐝𝐞𝐯𝐞𝐥𝐨𝐩𝐞𝐫, I build technical solutions for client's problems from user interfaces, and backend services to infrastructure-as-code solutions. As a 𝐦𝐚𝐜𝐡𝐢𝐧𝐞 𝐥𝐞𝐚𝐫𝐧𝐢𝐧𝐠 𝐞𝐧𝐠𝐢𝐧𝐞𝐞𝐫, I create, validate and deploy predictive models.