All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.5.0 - 2026-08-26
Added
- Field documentation: fields accept a
:docoption (always stripped before the underlying Ecto macro runs). Placing the<!-- typed_ecto_schema: fields -->marker in the module's@moduledocreplaces it at compile time with a markdown list of every field, its typespec and its doc — the marker is the only trigger, so without it the:docoptions don't touch the@moduledoc. Independently of the marker, the generatedt/0now gets a@typedocwith the same fields list when the module doesn't define one (a user-defined@typedocis kept, with the same marker interpolation available) (#68, closes #41) - Experimental: opt-in named types for
Ecto.Enumfields via theadditional_types: trueschema option (per schema, e.g.typed_schema "people", additional_types: true) or the global defaultconfig :typed_ecto_schema, additional_types: true. Each enum field with statically-known values defines a public type with the union of its values, e.g.@type role() :: :admin | :user, usable from other modules' specs (#63, closes #39) - Experimental: support for
polymorphic_embed'spolymorphic_embeds_one/2andpolymorphic_embeds_many/2insidetyped_schemablocks, behind a compile-time flag (off by default):config :typed_ecto_schema, polymorphic_embed: true. The typespec is inferred as the union of the modules in the:typesoption, and the::override plus the:null/:enforceoptions are supported.polymorphic_embeddoes not become a dependency — the calls are matched by name (#64, closes #40) - When both experimental features above are enabled, polymorphic embed fields
also get a named type with the union of their
:typesmodules, e.g.@type channel() :: SMS.t() | Email.t()(the element union forpolymorphic_embeds_many; skipped when the types are not statically resolvable)
Fixed
- Schema function options are no longer evaluated in the module body, so
module aliases in pass-through options — e.g.
many_to_many(..., join_through: Book)— no longer create compile-time dependencies (matching plainEcto.Schema). Only the options the type builder actually reads are forwarded to it, and a compiler-tracer regression test guards against reintroducing such dependencies (#67, closes #38 and #26)
0.4.4 - 2026-08-24
Added
@primary_keynow accepts the enhanced:nulland:enforceoptions to control the generated primary key typespec, e.g.@primary_key {:id, :binary_id, autogenerate: true, null: false}(#61, closes #42)timestamps/1now honors the enhanced:nulland:enforceoptions, sotimestamps(null: false)generates non-nullable timestamp typespecs (#60, closes #29)
Fixed
- Compilation crash (
FunctionClauseError) forEcto.Enumfields with empty or non-literal:values: a::type override now always takes precedence over inference, and empty or non-literal values fall back toany()instead of crashing (#62, closes #57) - Deprecation warnings and dependency incompatibilities on Elixir 1.19/1.20
(
preferred_cli_envmoved todef cli, credo updated), thanks @saleyn (#58) - README example showed non-nullable timestamps; the actual (and intended) default is nullable (#60)
Changed
- CI now tests Elixir 1.14 through 1.20 with OTP 24 through 29 (#59)
0.4.3 and earlier
No changelog was kept up to and including 0.4.3. See the GitHub releases and the git history for what changed in earlier versions.