Dart运行时类型转换实现及泛型列表深克隆类型不匹配问题求助
List<dynamic> is not a subtype of List<double> in Generic Deep Clone The core issue here is that when your extension encounters a nested List, it gets typed as List<dynamic> during the is List check. Calling deepClone() on it then returns a List<dynamic> instead of the specific typed list you need (like List<double> or List<String>). Here are a couple of practical solutions to fix this:
Solution 1: Recursive Clone with Runtime Type Handling
We can adjust the extension to handle nested lists by checking their actual runtime types, ensuring we clone them into correctly typed lists:
extension DeepCloneExtension on List { List deepClone() { return map((element) { if (element is List) { // Recursively clone nested lists return element.deepClone(); } else { // For non-list primitives, return the value directly // For custom objects, add a clone method check here return element; } }).toList(); } }
When you call it, simply cast the result to your target type (Dart validates the type at runtime):
// Example 1: Double nested list List<List<double>> values = [[3, 4], [4, 1, 2]]; List<List<double>> cloneValues = values.deepClone() as List<List<double>>; // Example 2: Triple nested string list List<List<List<String>>> strValues = [[["hello"], ["world", "hi"]], [["cat"]]]; List<List<List<String>>> clonedStrValues = strValues.deepClone() as List<List<List<String>>>;
This works for any depth of nested lists and any primitive type. If you're working with custom objects, add a check for those and implement a clone method for them.
Solution 2: Generic Extension with Type Casting (More Type-Safe)
If you prefer to keep the generic structure, modify the extension to preserve element types during recursion:
extension Ext<T> on List<T> { List<T> deepClone() { final result = <T>[]; for (final element in this) { if (element is List) { // Clone the nested list and cast it to the expected type T final clonedNested = element.deepClone(); result.add(clonedNested as T); } else { result.add(element); } } return result; } } // Non-generic extension to handle root-level list recursion extension DeepCloneRoot on List { List deepClone() { return map((e) => e is List ? e.deepClone() : e).toList(); } }
This approach maintains the generic pattern while ensuring nested lists are cloned with their correct types. The non-generic extension acts as a fallback for the root list, keeping recursion consistent.
Why Your Original Code Failed
When you checked if (value is List), Dart upcasts the value to List<dynamic>. Calling value.deepClone() then uses the Ext<dynamic> version of the method, returning List<dynamic>. Trying to cast this to T (like List<double>) fails because List<dynamic> isn't a subtype of List<double> in Dart's type system.
内容的提问来源于stack exchange,提问作者Vishnubly

