Home > Enterprise >  Dart gives Unhandled Exception: type is not a subtype of type of 'value'
Dart gives Unhandled Exception: type is not a subtype of type of 'value'

Time:11-18

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).

Any help would be appreciated, thanks.

CodePudding user response:

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.)

  • Related