Skip to content

Schema Quick Reference

shaun edited this page Oct 27, 2021 · 7 revisions

Please search the test examples for details on how to use anything mentioned in this reference.

(require '[schema.core :as s]])

Any code example below using <S> (or any capitalized word) means you can replace it with any Schema. Any lower-case <foo> means it’s not a schema, but a different kind of value whose type is explained inline by the name or adjoining comment.

Use Schemas in “Schematized” defs

Schemas are used as annotations inside special “schematized” versions of Clojure’s core def functions.

(s/def foo :- <S>)
;; or
(s/def ^<S> foo)
  • s/def
  • s/defn s/fn s/letfn
  • s/defmethod
  • s/defrecord

All values below listed as “Schemas“ can be used as annotations in the forms above.

Literal Schemas (exact values)

  • (s/eq <foo>) must be equal to the given literal value foo
  • (s/enum <a> <b> <c> ...) must be equal to any of the given literal values

Arbitrary Schema

  • (s/pred <f>) must satisfy the given predicate function f

Primitive Schemas (Leaf Schemas)

  • s/Any
  • s/Bool
  • s/Int
  • s/Inst (#inst date type)
  • s/Keyword
  • s/Num
  • s/Regex
  • s/Str
  • s/Symbol
  • s/Uuid (#uuid type)

Can be Nil

  • (s/maybe <S>) a non-nil value must satisfy this schema

Native Types as Schemas

  • #"..." satisfies a regular expression
  • java.lang.String, java.lang.Number (etc) Java classes
  • long, double, (etc) Java primitive casts
  • js/Element (etc) JavaScript prototypes

Composite Schemas

  • [<S>] a sequence of values, each satisfying the same schema
  • {<K> <V>} a map of values, each satisfying the same key and value schema
  • #{<S>} a set of values, each satisfying the same schema
  • (s/queue <S>) a queue of values, each satisfying the same schema
  • (s/pair <A> <B>) a sequence of two values matching the two schemas

Children: Sequence Elements

  • (s/one <S>) a single, required position in a sequence
  • (s/optional <S>) a single, optional position in a sequence

Children: Map Keys

  • (s/required-key <literal>) or just :foo if literal is a keyword
  • (s/optional-key <literal>)

Children: Recursive

  • (s/recursive #'foo) where foo is the name of the outer schema

Abstract Schemas

  • (s/isa ...) is a child of a given parent in a hierarchy
  • (s/protocol Foo) satisfies a protocol Foo
  • (s/record Foo {...}) is a record Foo satisfying the map schema
  • (s/atom <S>) is an atom with a value satisfying this schema

Union Schemas

  • (s/either <A> <B> <C> ...) satisfy any of the given schemas (deprecated)
  • (s/conditional <fA> <A> <fB> <B> ...) satisfy the first schema whose preceding predicate function returns true
  • (s/if <f> <A> <B>) satisfy schema A if the predicate function returns true, otherwise satisfy schema B
  • (s/cond-pre <A> <B> <C> ...) satisfy the first schema that passes its pre-check (not its full validation like s/either)

Intersect Schemas

  • (s/both <A> <B> <C> ...) satisfy both/all the given schemas (deprecated)
  • (s/constrained <S> <f>) satisfies schema S and a post-condition f

Named Schemas

  • (s/named <S> <name>) creates a named schema where the name (rather than definition) is displayed when printing errors (name can be any type)
  • (s/defschema <name> <S>) same as (def <name> <S>) but records the name in the schema’s metadata

Function Signature Schemas

These are purely descriptive and only checks for ifn?.

  • (s/=> <Return> <Arg1> <Arg2> ...) single-arity function with explicit args
  • (s/=> <Return> <Arg1> <Arg2> ... & [<ArgRest>]) single-arity function with rest args
  • (s/=>* <Return> [...] [...] ...) multi-arity function

Appendix

Pre-checks

For understanding s/cond-pre

Internally, there are hidden “preconditions” for all core schemas, which allows Schema to quickly “pre-check” a value before running a more expensive, full validation:

  • Composite schemas (maps, vectors, sets, queues) only check the collection type in their precondition.

  • Primitive schemas (leafs) perform their full validation in their precondition.

  • (s/maybe <S>) precondition is true if nil?, otherwise uses S’s precondition

  • (s/conditional <fA> <A> <fB> <B> ...) precondition is true if any predicate function is true

  • (s/cond-pre <A> <B> <C> ...) precondition is true if any of the given schema’s predicates are true

  • (s/constrained <S> <f>) precondition same as S’s