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.
Motivation
It would be useful if an extension could declare that it implements an interface for the type it extends.
For example:
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:
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:
LerpDouble) introduce additional types solely to satisfy an interface.Lerper<T>) work well but require passing an additional object everywhere, even when the behavior naturally belongs to the type.Proposed feature
Allow an extension to declare that it implements one or more interfaces for the extended type.
For example:
or another syntax with equivalent semantics.
The compiler would then consider
doubleto satisfyLerpable<double>wherever the extension is in scope.Design considerations
A few questions would need to be addressed:
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:
double,int, etc.)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.