Getting Started
Installation
BaseTypeContracts depends on TypeContracts. Add both:
using Pkg
Pkg.add(["TypeContracts", "BaseTypeContracts"])Loading registers the contracts
There is nothing to declare. The moment you load the package, its __init__ registers structural contracts and behavioral invariants for the core Base abstract types into the TypeContracts registry.
using TypeContracts, BaseTypeContracts
registered_contracts() # now contains AbstractArray, AbstractDict, … and IterableChecking a type
Ask whether a concrete type satisfies a Base protocol with satisfies:
satisfies(Vector{Int}, AbstractArray).satisfied # true
satisfies(Matrix{Float64}, AbstractArray).satisfied # true
satisfies(Dict{String,Int}, AbstractDict).satisfied # true
satisfies(Set{Int}, AbstractSet).satisfied # true
satisfies(String, AbstractString).satisfied # true
satisfies(Int, Number).satisfied # truesatisfies returns a NamedTuple; .satisfied is the boolean, and the rest explains any failure.
The check convenience
satisfies, implements, @verify, and friends already work directly against a parametric concrete type like Vector{Int} — TypeContracts resolves it back to the registered AbstractArray UnionAll automatically, no special handling needed.
check is a further convenience on top of that: instead of naming one Base contract at a time, it returns every applicable one (matched by <: across the curated Base types this package covers) in a single Dict:
BaseTypeContracts.check(Vector{Int})
# Dict{Type, NamedTuple} with 1 entry:
# AbstractArray => (satisfied = true, …)Next steps
The Base Contracts — the exact methods and invariants behind each protocol.
Checking Types — structural checks, behavioral testing, and trait dispatch.