cljs.spec.alpha/multi-spec

macropreviously cljs.spec/multi-spec clojure.spec.alpha/multi-specEdit
(multi-spec mm retag)

Source docstring:
Takes the name of a spec/predicate-returning multimethod and a
tag-restoring keyword or fn (retag).  Returns a spec that when
conforming or explaining data will pass it to the multimethod to get
an appropriate spec. You can e.g. use multi-spec to dynamically and
extensibly associate specs with 'tagged' data (i.e. data where one
of the fields indicates the shape of the rest of the structure).

(defmulti mspec :tag)

The methods should ignore their argument and return a predicate/spec:
(defmethod mspec :int [_] (s/keys :req-un [::tag ::i]))

retag is used during generation to retag generated values with
matching tags. retag can either be a keyword, at which key the
dispatch-tag will be assoc'ed, or a fn of generated value and
dispatch-tag that should return an appropriately retagged value.

Note that because the tags themselves comprise an open set,
the tag key spec cannot enumerate the values, but can e.g.
test for keyword?.

Note also that the dispatch values of the multimethod will be
included in the path, i.e. in reporting and gen overrides, even
though those values are not evident in the spec.
Source code @ clojurescript:src/main/cljs/cljs/spec/alpha.cljc
(defmacro multi-spec
  [mm retag]
  `(multi-spec-impl '~(res &env mm) (var ~mm) ~retag))