In addition to core predicates, predicate-induced type inference also works for instance? checks. So, for example testing (instance? Atom x) will result in x being inferred of type cljs.core/Atom .

Because cond and when are macros built on top of if , predicate-induced inference also works as expected for expressions involving cond and when .

because x satisfies string? , it will be inferred to be of string type in the then branch (and thus cause a warning to be emitted because inc is being applied to it).

The type inference algorithm will now consider core predicates when inferring the types of locals used in conditional expressions.

Truthy-Induced Inference

In situations where a value could potentially be nil (represented by the symbol clj-nil in type tags), if a simple symbol referring to such a value is used as the test in a conditional, the type inference algorithm will infer that the value cannot be nil in the then branch.

This is perhaps best illustrated by way of example. Let’s say you have the following function:

(defn f [x] (when (even? x) (inc x)))

This function’s return type is #{number clj-nil} , meaning that either a number or nil can be returned.

The following function, which uses f and would previously be inferred as returning #{number clj-nil} , is now inferred as returning number :

(defn g [y] (let [z (f y)] (if z z 17)))