Welcome! Please see the About page for a little more info on how this works.

0 votes
in Spec by
edited by

An s/keys spec will silently do nothing if it is defined without any valid arg key ( :req, :req-un, :opt, :opt-un, :gen).

Using req-un instead of :req-un (symbol instead of keyword, perhaps accidentally):

user> (s/def ::foo (s/or :string string? :number number?))

user> (s/def ::foo-map-broken (s/keys req-un [::foo]))

user> (s/conform ::foo-map-broken {:foo []})
{:foo []}

;;arg key can be anything
user> (s/def ::foo-map-broken2 (s/keys 42 [::foo]))

user> (s/conform ::foo-map-broken2 {:foo []})
{:foo []}

My two cents: I tend to think calls to s/keys should be validated more aggressively so this produces an error. The only argument I can think of in favor of the current behavior is that the args to s/keys are effectively a map and maps are usually not treated as closed in Clojure. But 1> args that result in nothing happening still seem worth erroring on and 2> the user does not actually pass a map and may not realize that the implementation turns their arg keys and arg values into a map.

(I came across this behavior when clj-kondo flagged a spec of mine as incorrect and I noticed a typo just like above where I had req-un instead of :req-un. I fixed :req-un to be a keyword and this uncovered bugs in the spec but it had been a few months since I touched the code so I wished I had discovered it sooner :--) )

1 Answer

+1 vote

No, because a "bad" error key now might be a feature added later. In general, we don't validate things like this in most places in spec.

OK thanks for the reply. At least there's Kondo.