I try to understand how HMaps are supposed to work when typechecking. Consider this code:
(ns ^:typed.clojure scr.foo
(:require [typed.clojure :as t]))
(t/ann ^:no-check foo [t/Str -> (HMap :complete? false)])
(defn foo [q]
{(keyword q) "hello"})
(t/ann bar [-> (HMap :mandatory {:f t/Str} :complete? false)])
(defn bar []
(foo "f"))
(comment
(t/check-ns-clj 'scr.foo))
Typechecking results in:
Type mismatch:
Expected: (t/HMap :mandatory {:f t/Str})
Actual: (t/HMap :mandatory {})
in:
(foo "f")
I expected that the type of bar is more specific than foo and thus typechecks. How can I achieve this?You're right about everything except and thus typechecks. This would only type check if foo is more specific than bar.
As for how to achieve this, that's tough with Typed Clojure. The nuclear option is to make foo a macro. I don't think types are expressive enough to track (foo "f") => {:f "hello"}.
There might be a fancy way with t/Assoc, but I'm not sure.
I'm planning on having the type checker inline particular calls on an opt-in basis. It would be handy if the checker treated foo like a macro without having to actually change it.