Skip to content

Allow extensions to satisfy interfaces for the extended type #4722

Description

@leslmosnk2

Motivation

It would be useful if an extension could declare that it implements an interface for the type it extends.

For example:

abstract interface class Lerpable<T> {
  T lerp(T other, double t);
}

extension DoubleLerpable on double implements Lerpable<double> {
  @override
  double lerp(double other, double t) {
    return this + (other - this) * t;
  }
}

This would allow existing types, especially SDK types such as double, to participate in generic APIs that rely on interface constraints without requiring wrapper types.

For example:

class Animation<T extends Lerpable<T>> {
  // ...
}

Animation<double>(); // Would be valid

Today, this is impossible because built-in types cannot be modified to implement additional interfaces, and extensions do not contribute to a type's implemented interfaces.

Current workarounds

The available alternatives all have drawbacks:

  • Wrapper types (LerpDouble) introduce additional types solely to satisfy an interface.
  • Strategy objects (Lerper<T>) work well but require passing an additional object everywhere, even when the behavior naturally belongs to the type.
  • Runtime type checks sacrifice static type safety.

Proposed feature

Allow an extension to declare that it implements one or more interfaces for the extended type.

For example:

extension DoubleLerpable on double implements Lerpable<double> {
  @override
  double lerp(double other, double t) => ...;
}

or another syntax with equivalent semantics.

The compiler would then consider double to satisfy Lerpable<double> wherever the extension is in scope.

Design considerations

A few questions would need to be addressed:

  • How are conflicts handled if multiple extensions implement the same interface for the same type?
  • Should interface implementation only apply when the extension is imported and in scope?
  • Should there be restrictions similar to extension method resolution to ensure deterministic behavior?

One possible approach is to require that at most one applicable extension provides a given interface implementation in any library, producing a compile-time error otherwise.

Benefits

This would enable retroactive interface conformance for existing types, making generic APIs significantly more expressive while avoiding unnecessary wrapper types.

It would be particularly useful for:

  • Numeric abstractions (double, int, etc.)
  • SDK types that cannot be modified
  • Third-party types
  • Generic math, animation, interpolation, serialization, and formatting APIs

Other languages provide similar capabilities through mechanisms such as protocol conformances (Swift) or traits (Rust, with coherence rules). A Dart feature in this area would make it much easier to write generic libraries without requiring ownership of the participating types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureProposed language feature that solves one or more problems

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions