New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem converting List<dynamic> to nested lists #1574
Comments
It's dynamic all the way down, so you would have to do something like: var newList = asset
.map<List<List<String>>>((first) => first
.map<List<String>>((second) =>
second.map<String>((third) => (third + "") as String).toList())
.toList())
.toList();
return newList as List<List<List<String>>>; or
|
The When you do ar list1 = <List<Object>>[
<int>[1, 2],
<int>[3, 4]
]; then In short, using |
The That's exactly the same as A completely statically sound type system would not have downcasts at all. You'd only be able to down cast by testing and promoting, giving you an |
The biggest difference (to me) is that For I'm being inconsistent, and I know it. There is a syntactic hint that I'll probably never use |
@ChristianKleineidam, would List<List<List>> parse(dynamic json) =>
List<List<List>>.from(json);
void main() {
List<List<List>> success = parse([[[]]]);
List<List<List>> fail = parse([[]]); // Error
} Of course, if you don't actually provide a |
@Levi-Lesches The expression The result of |
Got it, I added in the JSON and everything broke. I tried going with recursion for deep casting, but that got too messy and I don't think it will work anyway. If there was a way to use |
is there any progress on this issue? |
There is currently no proposed features to make it easier to change a |
...did I figure this out? Someone please point out the very obvious bug I must be missing: // Imagine this is the new List<T>.from(List)
List<T> cast<T>(List list) {
final List<T> result = [];
for (final element in list) {
// If T is a List, we want to cast every element of that list first
// Let E be the type argument of T, such that T = List<E>
// Somehow, Dart is smart enough to use `cast` here as `cast<E>(element)`
T castedElement = T is List ? cast(element) : element;
result.add(castedElement);
}
return result;
}
List<dynamic> getNestedInts() => [[1, 2, 3], [4, 5, 6]];
List<dynamic> getNestedStrings() => [[["this", "is"], ["a", "lot"]], [["of", "really"], ["long", "strings"]]];
void main() {
List<dynamic> list1 = getNestedInts();
List<List<int>> nestedInts = cast<List<int>>(list1);
print(nestedInts.runtimeType); // JSArray<List<int>>
List<dynamic> list2 = getNestedStrings();
List<List<List<String>>> nestedStrings = cast<List<List<String>>>(list2);
print(nestedStrings.runtimeType); // JSArray<List<List<String>>>
} |
Okay, I found it. You can't actually do So the new code is: void main() {
List<dynamic> list1 = getNestedInts();
print(list1.runtimeType); // JSArray<dynamic>
List<List<int>> nestedInts = List.from(list1);
print(nestedInts.runtimeType); // JSArray<List<int>>
print(nestedInts.first); // [1, 2, 3]
List<dynamic> list2 = getNestedStrings();
print(list2.runtimeType); // JSArray<dynamic>
List<List<List<String>>> nestedStrings = List.from(list2);
print(nestedStrings.runtimeType); // JSArray<List<List<String>>>
print(nestedStrings.first); // [[this, is], [a, lot]]
} While this won't, say, convert If we really wanted to have more control, Dart would need to let us inspect Type Arguments, specifically to extract |
@Levi-Lesches yeah but it only works if in
Also, just in case if any one find this info useful 🤷♂️:- |
Right, thanks, I knew I was missing something obvious. So in that case, yes, I'd refer to my updated findings that we would need to have a way to inspect a type argument and extract its generics. We wouldn't have to rely on compile-time safety, since we all seem to be on the same page that dynamic runtime checks are okay. |
I spent another hour with a bug that came down to the same issue. How about introducing asDeep as a new way to do the cast that actually transforms the types as desired? Then the error message could highlight that the user might want to use asDeep. (for context, I'm using SembastDb as my database and it returns lists that I saved in it in a way that doesn't have deep type information). |
An Alternatively, if the input is a JSON structure (so the possible types are known), it's probably possible to find the most precise types for the structure by traversing and rebuilding on the way back. |
I'm a bit unsure what you mean with JSON structure here. In my use-case, I don't have access to a JSON but get an object from sembast which inturn internally has something like a JSON sturcture. Do you think that sembast (https://pub.dev/packages/sembast) is doing something wrong here and should give me other objects? |
I'm saving data objects in sembastdb and reading them again and then they come back as dynamic. Normally, Dart makes it easy to cast dynamic objects to their real type.
This doesn't seem to work with nested lists. To be able to read convert List back to List<List<List>>, currently, I seem to have to do:
And can't simply do:
return asset as List<List<List<String>>>
I can't even do:
Which produces the error
type 'List<dynamic>' is not a subtype of type 'List<List<List<String>>>' in type cast
.I first opened an issue with SembastDb but it seems to be a more general problem with nested list and dynamic.
This seems to be all happening while at the same time in the debugger the actual types look like they should be convertible.
The text was updated successfully, but these errors were encountered: