1

I have this small code snippet:

class A<T> {
  A(this.a);
  
  final T a;
}


void main() {
  final a = A(true);
  print(a);
  print(a as A<bool>);
  
  final b = A<Object>(true);
  print(b);
  print(b as A<bool>);  
}

I'm receiving the object b from a library/API which is a A<Object> (and I don't have control over it), but I know it is actually a A<bool> in my specific case. I'm trying to cast it to A<bool> (as in my code snippet with b). But I get an error saying that A<Object> is not a subtype of A<bool>.

Here are the logs from the code snippet pasted above:

Instance of 'A<bool>'
Instance of 'A<bool>'
Instance of 'A<Object>'
Uncaught Error: TypeError: Instance of 'A<Object>': type 'A<Object>' is not a subtype of type 'A<bool>'

How can I cast b (a A<Object>) into a A<bool>?

Valentin Vignal
  • 6,151
  • 2
  • 33
  • 73
  • bool is a primitive, hence not an Object so what you're trying to do is impossible without some workarounds. – krumpli Apr 19 '22 at 13:29
  • I'm a bit confused, I can do `late final Object f; f = true; print(f as bool);` and I don't get any error even though I wrote `f as bool` with `f` of type `Object`. – Valentin Vignal Apr 19 '22 at 13:43
  • Also, I get the same result if I replace `A` with `A`: `Uncaught Error: TypeError: Instance of 'A': type 'A' is not a subtype of type 'A'` – Valentin Vignal Apr 19 '22 at 13:46
  • Actually now that i look into it bool is a class so now I'm intrigued. print(a as A); <-- this casts a bool to another bool so it's unnecessary. However the bool class in dart is a wrapper for bool.fromEnvironment(String) which is a factory method. If this under-the-hood method does something to prevent the cast, I'm sure i don't know. – krumpli Apr 19 '22 at 13:53
  • @krumpli [Dart does not have primitives.](https://stackoverflow.com/a/65073696/) Everything is an `Object`. – jamesdlin Apr 19 '22 at 15:36

2 Answers2

2

How can I cast b (a A<Object>) into a A<bool>?

You can't. They're not the same type.

b was constructed as an A<Object>, so its runtime type is A<Object>, regardless of whether b.a happens to be referring to a bool. A cast with as changes the static (known to the compiler) type of an object, but you cannot change an object's runtime type. If you want an object with a different runtime type, you must construct a separate object.

Let's consider a slightly different example:

class C<T> {
  T value;

  C(this.value);
}

C<T> is the same thing as A<T> except that its member is not final. If casting an object with a runtime type of C<Object> to C<bool> were allowed, then we could have the following:

final c = C<Object>(true);
final casted = c as C<bool>; // Should this be allowed?
c.value = 'Hello world!'; // Legal since `c.value` is of type `Object`.
bool someBool = casted.value; // ???

Arguably the case for casting A is different; A's member is final and therefore wouldn't lead to the above scenario. However, I'd expect that that kind of exception would add a lot of complexity and possibly could make things even more confusing.

Also see: https://stackoverflow.com/a/67223011/

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
0

The following code can cast it. dont know if it works in your case.

var c = A<bool>(b.a as bool);
/// OR
extension Cast on A<Object> {
  A<bool> cast() => A<bool>(a as bool);
}
Greed
  • 21
  • 2
  • Thank you, but my example is a minimal on to illustrate the issue. I won't be able to do that with a bigger/more complicated object – Valentin Vignal Apr 19 '22 at 16:33