I have a map of which I'd like to specify two optional keys, but they must not exist both. I'm trying to express this in spec but I'm having a hard time. You can't use and and or in the :opt part of the s/keys spec either, so that makes it particularly hard.
Can someone help me out?
I've come up with a solution, but would love to hear from more experienced users.
(defn only-one-key-of [kws]
(fn [m]
(not
(set/subset? kws
(into #{} (keys m))))))
(s/def ::some-map
(s/and
(s/keys :req [:a]
:opt [:b :c :d])
(only-one-key-of [:b :c])))
(comment
(s/valid? ::some-map {:a 1 :b 2 :c 3}) ;; correctly gives `false`
)I think that's the right approach
Nice. Thanks for your feedback
small warning: only-one-key-of might be a bit misleading, it won't give the expected result if there are more than 2 keywords
Yes, it was not very well-defined, it also didn't for just one parameter. I've redone the implementation to be more robust now. Thanks for pointing it out though 🙂