4

I have an abstract class ImageUpdate. Two classes, NewImage and ExistingImage implement ImageUpdate.

I have a variable imageUpdates of type List<ImageUpdate>.

When I try adding a variable of type NewImage to the List, I get this error:

Unhandled Exception: type 'NewImage' is not a subtype of type 'ExistingImage' of 'value' 

I am pretty stumped, since the list is of ImageUpdate and not ExistingImage, so I have no idea how to debug it, especially since Dart is type safe (nowhere am I using dynamic).

1
  • 1
    It's very hard to answer this question without seeing reproducible code. My guess is that you think you have a List<ImageUpdate> but it's actually a List<ExistingImage>. For example, that could happen if you had List<ImageUpdate> list = <ExistingImage>[]; and then tried to add a NewImage to list. Commented Nov 17, 2021 at 3:53

1 Answer 1

7

I suspect that you have code similar to:

class Base {} class Derived1 extends Base {} class Derived2 extends Base {} List<Base> makeList() { var list = [Derived1()]; return list; } void main() { var list = makeList(); list.add(Derived2()); // TypeError } 

What happens is that the List object is originally created as a List<Derived1>. (That is, list.runtimeType will be something like List<Derived1>, not its static (declared) type of List<Base>.) Then, when you try to add a Derived2 object to list, it will fail at runtime because list's actual, runtime type is List<Derived1>, which does not allow Derived2 elements.

This ultimately stems from Dart allowing implicit type conversions from GenericClass<Derived> to GenericClass<Base> if Derived derives from Base. This is useful in many cases, but it also can lead to situations like this one that fail at runtime.

You can fix this by explicitly stating that you want a List<Base> object:

List<Base> makeList() { var list = <Base>[Derived1()]; // Note the explicit type. return list; } 

or, if that's not possible, by creating a new List<Base> object:

  • var list = <Base>[...makeList()];
  • var list = List<Base>.from(makeList());

(In this particular situation, List.of(makeList()) also would work since it would create a new List object with the static type, but I wouldn't use that since being explicit about the type conversion would be more readable.)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.