These are three merely different approaches to give the developer some type safety. All the three offer their own DSL to describe the schema/type of data but they are very different in philosophy. They are all actively maintained and have a nice community.
This is an opinionated overview based of my experiences.
core typed
core typed tries to extend the clojure language with additional macros to annotate functions and vars with static type information. It then uses static type analysis to ensure that the code matches the type info (that is it produces and consumes data of the right types).
Some advantages:
- Static typing in general is a very strong tool. If you are familiar with staticly typed programming languages you will appreciate this very much.
- Many bugs can be found during compilation time. No more NullPointerExceptions!
Some drawbacks:
- Changing something in type or code may require extra work to propagate the changes through all parts of your code. And sometimes it is just too complicated to write type info or correct programs.
- Static code checking will slow down your compile times and may slow down your development workflow.
Schema
In Schema you also write type annotations but type checking happens runtime. It encourages you to construct schema declarations dynamically and lets you specify where you want to check for schema and where you do not want its funcionality.
Some advantages:
- Very friendly DSL to describe data schema.
- Various tools. For example: Data generation for generative testing, tools to explain why a schema does not match.
Some disadvantages:
- Only checks for schema where and when you tell it to do so.
- External library, not supported by the core team.
Spec
Spec is the latest player with a philosophy borrowed from Racket lang. It is (going to be) part of the Clojure core library from the Clojure version 1.9.
The basic idea is to have entity types specified by the (namespaced) keys in a map object. Spec declarations are stored in the application's registry bound to namespaced keywords. Spec is very strong in sequence validation.
Some advantages:
- Part of the Clojure core, not an external library. It is now used for parsing macro arguments and also for documentation purposes.
- The community is very excited about it resulting in interesting ideas such as using spec in genetic programming and generative testing.
Some disadvantages:
Personally, core.typed feels intimidating and core.spec feels immature so I use schema in production. My advice is the following:
- If you need static type checking then core.typed is the way to go.
- If you want to do parsing then core.spec is a nice choice.
- If you want simple type descriptions then schema will be a good fit.