Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strip-extra-keys-transformer not working with s/or if ors predicates are non- map validating specs #255

Open
tylernisonoff opened this issue Jun 27, 2021 · 3 comments

Comments

@tylernisonoff
Copy link

This is similar to Issue 178 (Fixed by PR 219, but for a specific case.

I'm not sure if this is intended, but it was surprising to me.

Consider the following case where we want to allow something like either {:a 1} or {:b "foo"}

  (s/def ::a int?)
  (s/def ::b string?)
  (s/def ::c (s/or
               :a (s/keys :req-un [::a])
               :b (s/keys :req-un [::b])))
  ((s/valid? ::c {:a 1})
  ; => true
  (st/coerce ::c {:a 1} st/strip-extra-keys-transformer)
  ; => {}

However, If i change ::c to:

(s/def ::c (s/or
               :a (st/spec (s/keys :req-un [::a]))
               :b (st/spec (s/keys :req-un [::b]))))

NOTE: the st/spec s

Now we get:

 (s/valid? ::c {:a 1})
  ; => true
  (st/coerce ::c {:a 1} st/strip-extra-keys-transformer)
  ; => {:a 1}

My expectation is either of these two should be able to be coerced, is that correct?

@opqdonut
Copy link
Member

Thanks for finding this, great repro & workaround of the or + strip-extra-keys-transformer behaviour!

@opqdonut
Copy link
Member

Some proposed solutions here: #212 (comment)

@opqdonut
Copy link
Member

e31461d adds a failing test case to the existing issue-179 test, namely:

      (is (= (st/coerce ::vehicle bike st/strip-extra-keys-transformer)
             {:wheels 2}))

It looks like whether you use named or inline specs affects this. Note how both forks of this or work:

(s/def ::s (s/or :x (s/keys :req-un [::keyword ::int])
                 :y (s/keys :req-un [::keyword ::date])))

but here only the first one (:car) works:

(s/def ::car (s/keys :req-un [::doors]))
(s/def ::bike (s/keys :req-un [::wheels]))
(s/def ::tires (s/coll-of (s/and int?) :into #{}))
(s/def ::vehicle (s/or :car ::car
                       :bike ::bike))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants