Closed FabrizioG202 closed 37 minutes ago
You don't always want this behavior. Bounding T
to T
extends E
would prevent one to check against a supertype instead of a subtype.
Consider this example:
void main() {
final fooList = <Foo>[];
fooList.add(FooAB());
fooList.add(FooA());
fooList.add(FooB());
print(ol.whereType2<B>());
}
abstract interface class A {}
abstract interface class B {}
final class Foo {}
final class FooAB extends Foo implements A, B {}
final class FooA extends Foo implements A {}
final class FooB extends Foo implements B {}
extension <E> on Iterable<E> {
Iterable<T> whereType2<T extends E>() sync* {
final iterator = this.iterator;
while (iterator.moveNext()) {
if (iterator.current case final T current) {
yield current;
}
}
}
}
This program does not compile, because of the bound. Removing the bound (or using whereType
directly) makes it work as intended.
You don't need a complicated example to demonstrate the phenomenon.
if ("Hello" is int) { // no warning
print(0);
}
in contrast
if (!true) { // warning: dead code blah blah
}
This is really just a minor inconvenience with the Iterable's API.
Take for example the following code snippet:
We should know at compile time that the filtered iterable will always be empty since int is not a subtype of
WithInt
. This is a trivial example, but I found out that in more complex scenarios, especially when adding wrapper classes (such as WithInt) the code still compiles fine but suddenly filtering always yields no results.I was wondering, since dart supports syntax like
<T extends E>
while declaring type parameters on functions, why is this not used in the signature of the whereType method? Having something like that would make it so that the code above does not compile. Moreover, it looks like it should be a relatively easy fix.Is there a reason behind this design?