Skip to main content
An extension type is a compile-time, zero-cost abstraction that wraps an existing underlying type with a new, distinct static type interface. At runtime, the extension type is completely erased, and the underlying representation is used directly, incurring no object allocation or indirection overhead.

Syntax

An extension type declaration requires a name and exactly one underlying representation variable, which acts as the primary constructor.
Example:

Technical Mechanics

1. Interface Encapsulation

By default, an extension type completely hides the interface of its underlying type. If you call a method on the extension type that exists on the underlying type but is not explicitly declared in the extension type, the compiler will throw an error.

2. The implements Clause

To expose the underlying type’s interface, an extension type can implement its representation type. This establishes a subtyping relationship where the extension type becomes a static subtype of the underlying type.
An extension type can also implement other extension types, provided they share the same underlying representation type or a supertype of it.

3. State Restrictions

Extension types are strictly limited to their single representation variable. They cannot declare additional instance variables. They can, however, declare static variables.

4. Constructors

The representation variable automatically generates a primary constructor. You can define additional named or factory constructors, but they must ultimately initialize the single representation variable.

Type Assignability and Casting

Because extension types are static constructs, the Dart analyzer enforces strict rules regarding assignability:
  • Underlying to Extension: You cannot implicitly assign the underlying type to the extension type. You must use the constructor or an explicit cast.
  • Extension to Underlying: You can implicitly assign an extension type to its underlying type only if the extension type implements the underlying type. Otherwise, it requires an explicit cast or accessing the representation variable.
When using the as operator, Dart performs a runtime cast. Because the extension type is erased at runtime, casting to an extension type is evaluated exactly as casting to its underlying representation type.

Runtime Erasure and Type Checking

Because extension types are erased during compilation, runtime type checks (is) and runtime type queries (.runtimeType) evaluate against the underlying representation type, not the extension type. The is operator is always a runtime type test. When you check if an object is an extension type, the compiler erases the extension type and performs the runtime check against the underlying type.
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More