Skip to content

Instantly share code, notes, and snippets.

@mfikes
Last active May 17, 2020 02:37
Show Gist options
  • Save mfikes/3837f510aad3e8ff766eb9071ef66b2b to your computer and use it in GitHub Desktop.
Save mfikes/3837f510aad3e8ff766eb9071ef66b2b to your computer and use it in GitHub Desktop.
Seeing the inferred type of a ClojureScript expression

If you are curious about the types inferred by ClojureScript, it is easy to get some insight using a macro:

(defmacro inferred-type [form]
  `'~(cljs.analyzer/infer-tag &env
       (cljs.analyzer/no-warn (cljs.analyzer/analyze &env form))))

This is the kind of dev-time macro you could refer using the new user.cljs feature.

This gist sets this macro up along with a REPL, running in a branch of ClojureScript containing all of the in-flight type inference revisions:

clj -Srepro -Sdeps '{:deps {github-mfikes/gist-3837f510aad3e8ff766eb9071ef66b2b {:git/url "https://gist.github.com/mfikes/3837f510aad3e8ff766eb9071ef66b2b" :sha "ee58ef464e20e482aec4ef0928f4e61a9ddc77de"}}}' -m cljs.main -co @compile-opts.edn -re node -r

Here is an example of using it:

cljs.user=> (inferred-type 1)
number
cljs.user=> (inferred-type "a")
string
cljs.user=> (inferred-type (if x 1 "a"))
#{number string}

Checking an inferred type inside an expression:

cljs.user=> (let [x (+ 2 3)]
  (inferred-type x))
number

You can even see the new function return type inference in action:

cljs.user=> (defn foo [x]
  (cond
    (pos? x) "a"
    (neg? x) 3
    :else true))
#'cljs.user/foo
cljs.user=> (inferred-type (foo 1))
#{boolean number string}

Inferred types for if expressions

cljs.user=> (inferred-type (if "a" 1 :kw))
number

and the implications for and / or:

cljs.user=> (inferred-type (or nil 1 "a"))
number
{:repl-requires [[cljs.repl :refer [doc source pst]]
[type-utils :refer [inferred-type]]]
:warnings {:single-segment-namespace false}}
{:paths ["."]
:deps {org.clojure/clojurescript {:git/url "https://github.com/mfikes/clojurescript" :sha "1d5784767147c9f12670cfe157984e90f5cf3f29"}}}
(ns type-utils)
(defmacro inferred-type [form]
`'~(cljs.analyzer/infer-tag &env
(cljs.analyzer/no-warn (cljs.analyzer/analyze &env form))))
(ns type-utils
(:require-macros [type-utils]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment