We were discussing at work today, and this cropped up:
ardoq.core> (spec/def :foo/foo string?)
;; => :foo/foo
ardoq.core> (spec/def :foo/bar int?)
;; => :foo/bar
ardoq.core> (spec/def ::test (spec/keys :req [:foo/foo]))
;; => :ardoq.core/test
ardoq.core> (spec/valid? ::test {:foo/foo "foo" :foo/bar 1})
;; => true
ardoq.core> (spec/valid? ::test {:foo/foo "foo" :foo/bar "1"})
;; => false
In the last example, :foo/bar is not mentioned in ::test but seems to still be checked. What am I not seeing?s/keys will cause all namespace qualified keys to be checked
Right, it’s there in the docstring: > In addition, the values of all namespace-qualified keys will be validated > (and possibly destructured) by any registered specs. TIL.
Which still is a bit strange since then:
ardoq.core> (s/def :foo/foo string?)
;; => :foo/foo
ardoq.core> (s/def :foo/bar int?)
;; => :foo/bar
ardoq.core> (s/def ::test (s/keys :req []))
;; => :ardoq.core/test
ardoq.core> (s/valid? ::test {:foo/foo "foo" :foo/bar "1"})
;; => false
ardoq.core>
Which makes you wonder why even bother with :req ?You still need to be able to express what key set is required
I guess for opt it's debatable. It's mostly for gen there
True
Also if you have a ns qualified key that points to a value that does not conform to the spec with the same key, no matter where, it's likely a smell. Integrant pushes toward this for instance, I am not a fan of that part of the lib.
opt is used for gen