What are Extension Types?
Introduced in Dart 3.3, extension types allow you to create a compile‑time wrapper around an existing type. They are similar to extension methods but provide a new type that is distinct at compile time while having zero runtime overhead. Extension types are ideal for adding type safety to primitive types (like wrapping String with EmailAddress) or for creating domain‑specific types without the cost of creating a full class.
Why Use Extension Types?
- Type safety – prevent accidental mixing of conceptually different values of the same underlying type (e.g.,
EmailvsName).
- Type safety – prevent accidental mixing of conceptually different values of the same underlying type (e.g.,
- Zero runtime cost – no extra object allocation; the wrapper exists only at compile time.
- Clearer API – self‑documenting types make interfaces more expressive.
- Opt‑in to existing methods – you can expose or hide methods of the underlying type.
Syntax of Extension Types
An extension type is declared using extension type followed by a name and the underlying type in parentheses. It can define methods, getters, and even new constructors.
Underlying Representation
The extension type wraps the underlying value but does not create a new object at runtime. The wrapper is just a compile‑time type; the underlying representation is the same as the original type. This means extension types are zero‑cost – they don't allocate extra memory and have no performance penalty.
Exposing Underlying Members
By default, the wrapper does not expose any members of the underlying type. You must explicitly forward methods or properties you want to expose. This gives you full control over the public API.
Constructors and Factories
Extension types can have constructors, including redirecting constructors and factory constructors. They can also perform validation during construction.
Implicit Exposure (Shortcut)
You can use the on keyword to automatically expose all members of the underlying type. This is a shortcut when you want the extension type to behave like the original type but with a different type name.
Extension Types vs Regular Extensions
- Regular extension adds methods to an existing type (like
String). It does not create a new type.
- Regular extension adds methods to an existing type (like
- Extension type creates a new type that wraps an existing type. It's a distinct type at compile time, with zero runtime overhead.
Use Cases
- Domain‑specific types –
EmailAddress,UserId,ProductId.
- Domain‑specific types –
- Unit conversion –
Meters,Feet,Celsius,Fahrenheit.
- Unit conversion –
- Validation wrappers – ensure valid values at construction.
- API boundaries – enforce correct types without runtime cost.
Complete Example
Key Takeaways
- Extension types create new types with zero runtime overhead.
- They are defined with
extension type Name(UnderlyingType representation).
- They are defined with
- Use them to add type safety to primitive types, perform validation, and hide implementation details.
- They have constructors, can expose or hide underlying members, and can be used in
onclauses to automatically forward all members.
- They have constructors, can expose or hide underlying members, and can be used in
- Ideal for domain modelling, units, and ensuring correct usage at API boundaries.