You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart运行时类型转换实现及泛型列表深克隆类型不匹配问题求助

Fixing 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 21:28:09