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

Merging :map and :multi #493

Open
kennyjwilli opened this issue Jul 29, 2021 · 3 comments
Open

Merging :map and :multi #493

kennyjwilli opened this issue Jul 29, 2021 · 3 comments
Labels
enhancement New feature or request

Comments

@kennyjwilli
Copy link

Coming from Clojure Spec, I would expect merging a :map with a :multi to work intuitively. Instead, I hit the merge-default behavior in malli.util/merge, which drops the first schema in favor of the second one. Naively, it seems like :multi could be handled more elegantly. Take the following scenario.

;; Malli Schema 
(def Base [:map [:a string?]])
(def Full [:merge Base [:multi {:dispatch :type}
                        [:type1 [:map [:type1-k string?]]]]])

;; Same Schema, written in Spec
(s/def ::a string?)
(s/def ::base (s/keys :req-un [::a]))

(defmulti base-spec :type)

(s/def ::type1-k string?)
(defmethod base-spec :type1 [_] (s/keys :req-un [::type1-k]))

(s/def ::full
  (s/merge ::base (s/multi-spec base-spec :type)))

If I m/explain a value missing the :a key, Malli will return true. I expected an explain that tells me I am missing a key.

(m/explain Full {:type    :type1
                 :type1-k ""})
=> nil

Here is Spec's output.

(s/explain-data ::full {:type    :type1
                        :type1-k ""})
=>
#:clojure.spec.alpha{:problems ({:path [],
                                 :pred (clojure.core/fn [%] (clojure.core/contains? % :a)),
                                 :val {:type :type1, :type1-k ""},
                                 :via [:example/full
                                       :example/base],
                                 :in []}),
                     :spec :example/full,
                     :value {:type :type1, :type1-k ""}}

For our use cases, merging a :map with a :multi is a very common scenario. Is there interest in supporting this natively?

@ikitommi ikitommi added the enhancement New feature or request label Jul 30, 2021
@ikitommi
Copy link
Member

This is asked a lot. Just merge with all branches of do we need to derive effective types for schemas first (#264)?

@oryband
Copy link

oryband commented Oct 4, 2021

Hi @kennyjwilli - did you solve this issue non-natively with Malli for the time being? If so, is it possible to share with the above as an example please? Thank you!

@kennyjwilli
Copy link
Author

Yes @oryband, though I'm not fully satisfied with the solution, it does work for our use case -- just data validation. At each :merge, I am able to loop through the children, validating if the data passes the child schema.

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

No branches or pull requests

3 participants