Had another go at pushing this runner forward and had to give up on the extensions for the multimethod I'm afraid. I found out I can just ignore the var though, so I'm annotating it with :no-check now which has got me past that part.
I'm running into something weird though, I merge these maps:
(t/defalias TypedClojureExInfoData
(t/HMap
:mandatory {:form t/Any
:type-error t/Keyword
:env (t/HMap
:mandatory {:line t/Num
:column t/Num
:file t/Str})}))
(t/defalias TypeError
(t/Merge
TypedClojureExInfoData
(t/HMap
:mandatory {:message (t/Nilable t/Str)})))
But then when I use it here:
(t/ann error->str [background-check.runner/TypeError :-> t/Str])
I get an error because all of the properties are now "t/Any" other than the :message. Here's my env that shows this, sorry it's not pretty printed or anything.
│ {:env {p__118482__#0 (t/HMap :mandatory {:form t/Any, :type-error t/Any, :env t/Any, :message (t/Nilable t/Str)})}, :props (), :aliases {map__118809__#0 {:id p__118482__#0}, map__118809__#1 {:id p__118482__#0}, _error__#0 {:id p__118482__#0}, type-error__#0 {:id p__118482__#0, :path [(Key :type-error)]}, env__#0 {:id p__118482__#0, :path [(Key :env)]}, _form__#0 {:id p__118482__#0, :path [(Key :_form)]}, _data__#0 {:id p__118482__#0, :path [(Key :_data)]}, _message__#0 {:id p__118482__#0, :path [(Key :_message)]}}}Ohhh that makes sense! Thank you, I should've tried this. I did see the concept of open/closed in the docs and considered closing them because it might prevent typo bugs but then thought "meh, it's Clojure-y to allow some extra keys sometimes". Better to be explicit, less confusion that way 🙂 thanks as always, I really really appreciate the tutoring you've been giving me with this. I'll have to spread the good word at reClojure in London on Monday 🎉
Is this maybe a bug?
Oh, the problem is that both maps are open.
The right map is implicitly (t/HMap :optional {:form Any :type-error Any, :env Any ...})
So when you merge these maps, it combines (t/HMap :mandatory {:type-error Kw}) with (t/HMap :optional {:type-error Any}), which is (t/HMap :mandatory {:type-error (U Kw Any)}) => '{:type-error Any}
The easiest fix would be to use t/Assoc instead of t/Merge
You could also constrain the right map using :complete? true.
Ah interesting! I was also wondering how to assoc into the mandatory or optional parts of the HMap.
I couldn't work out the syntax for t/Assoc sadly, but I did get it working with a closed HMap and merge, yay!
Merge is more flexible, but you might have missed a quote on the keyword singleton type: (t/Assoc TypedClojureExInfoData ':message (t/Nilable t/Str))
t/Assoc takes flat k/v pairs of types. (t/Val :message) is also written ':message.