首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >'(TypleClass) =>字符串‘不是类型(动态) =>字符串的子类型

'(TypleClass) =>字符串‘不是类型(动态) =>字符串的子类型
EN

Stack Overflow用户
提问于 2022-08-31 22:07:53
回答 1查看 106关注 0票数 0

首先,我已经在Flutter的团队存储库上提交了一个问题,因为对我来说,这是一个关于Flutter/Dart的问题,但也许我错了。

复制步骤

  1. 在代码flutter run上执行示例
  2. 有两种类型的流以类似的方式运行,我创建了上面的项目来表示这些场景
  3. 您将发现两个按钮,在每种情况下,这些按钮都将被重定向到一个可以触发每次故障的新页面。

预期的结果:“小部件示例”中创建一个具有类型属性的通用有状态小部件TypeErrorWidget<T>

代码语言:javascript
复制
final IdMapper<T> idMapper;

其中IdMapper<T>被定义为:

代码语言:javascript
复制
typedef IdMapper<T> = String Function(T item);

稍后,将在状态内访问此属性,以映射可迭代的项并提取ids,并提供如下函数:

代码语言:javascript
复制
_itemsIds = widget.items.map((e) {
      return widget.idMapper(e);
    }).toList();

我希望得到I作为List<String>的列表

实际结果:

但是,当运行时到达这一行时,它会失败地抱怨以下几点:'(ExampleListItem) => String' is not a subtype of type '(dynamic) => String',它没有多大意义,因为dynamic应该包含我的自定义类型。

代码样本

lib/presentation/widgets/type_error_widget.dart

代码语言:javascript
复制
class TypeErrorWidget<T> extends StatefulWidget {
  final Iterable<T> items;
  final IdMapper<T> idMapper;

  const TypeErrorWidget({
    Key? key,
    required this.items,
    required this.idMapper,
  }) : super(key: key);

  @override
  State<TypeErrorWidget> createState() => _TypeErrorWidgetState();
}

class _TypeErrorWidgetState extends State<TypeErrorWidget> {
  late List<String> _itemsIds;

  @override
  void initState() {
    _itemsIds = widget.items.map((e) {
      return widget.idMapper(e); <- it throws!
    }).toList();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text("I'll crash"),
        Text(_itemsIds.toString()),
      ],
    );
  }
}

class WidgetExamplePage extends StatefulWidget {
  const WidgetExamplePage({super.key});

  @override
  State<WidgetExamplePage> createState() => _WidgetExamplePageState();
}

class _WidgetExamplePageState extends State<WidgetExamplePage> {
  bool _makeItCrash = false;
  bool _makeItWork = false;

  final List<ExampleListItem> _items = const [
    ExampleListItem(
      id: "id1",
      title: "Title1",
    ),
    ExampleListItem(
      id: "id2",
      title: "Title2",
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Widget error")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            if (_makeItCrash)
              TypeErrorWidget<ExampleListItem>(
                items: _items,
                idMapper: (item) {
                  return item.id;
                },
              ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _makeItWork = false;
                  _makeItCrash = true;
                });
              },
              child: const Text("Make it crash"),
            ),
            if (_makeItWork && !_makeItCrash)
              TypeWorkaroundWidget<ExampleListItem>(
                items: _items,
                idMapper: (item) {
                  return item.id;
                },
              ),
            if (!_makeItCrash)
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    _makeItWork = true;
                    _makeItCrash = false;
                  });
                },
                child: const Text("Make it works"),
              ),
          ],
        ),
      ),
    );
  }
}
代码语言:javascript
复制
 Logs  
代码语言:javascript
复制
The following _TypeError was thrown building KeyedSubtree-[GlobalKey#196d8]:
type '(ExampleListItem) => String' is not a subtype of type '(dynamic) => String'

The relevant error-causing widget was:
  Scaffold
  Scaffold:file:///Users/victor/Documents/personal/development/flutter/type_issues/lib/presentation/pages/widget_example_page.dart:29:12

When the exception was thrown, this was the stack:
#0      _TypeErrorWidgetState.initState.<anonymous closure> (package:type_issues/presentation/widgets/type_error_widget.dart:26:21)
#1      MappedListIterable.elementAt (dart:_internal/iterable.dart:413:31)
#2      ListIterator.moveNext (dart:_internal/iterable.dart:342:26)
#3      new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:189:27)
#4      new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
#5      new List.of (dart:core-patch/array_patch.dart:51:28)
#6      ListIterable.toList (dart:_internal/iterable.dart:213:44)
#7      _TypeErrorWidgetState.initState (package:type_issues/presentation/widgets/type_error_widget.dart:27:8)
#8      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5015:57)
#9      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4853:5)
#10     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3863:16)
#11     MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6435:36)
#12     Element.updateChild (package:flutter/src/widgets/framework.dart:3592:18)
#13     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5964:32)
#14     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6460:17)
#15     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#16     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#17     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#19     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#20     StatelessElement.update (package:flutter/src/widgets/framework.dart:4956:5)
#21     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#22     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#23     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#24     StatelessElement.update (package:flutter/src/widgets/framework.dart:4956:5)
#25     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#26     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#27     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#28     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#29     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#30     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#31     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#32     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#33     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#34     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5904:32)
#35     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6460:17)
#36     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#37     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#38     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#39     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#40     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#41     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#42     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#43     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#44     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#45     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#46     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#47     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#48     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#49     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#50     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#51     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#52     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#53     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#54     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#55     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#56     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#57     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#58     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#59     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#60     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#61     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#62     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#63     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#64     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#65     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#66     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14)
#67     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#68     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#69     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#70     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#71     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#72     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#73     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#74     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#75     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#76     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#77     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#78     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#79     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#80     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#81     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#82     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#83     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#84     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#85     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#86     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#87     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#88     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#89     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#90     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#91     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#92     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#93     StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#94     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#95     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#96     Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#97     ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5)
#98     Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#99     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#100    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#101    Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#102    StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5)
#103    Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15)
#104    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16)
#105    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11)
#106    Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5)
#107    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2667:19)
#108    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#109    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#110    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#111    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#112    SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#113    _invoke (dart:ui/hooks.dart:148:13)
#114    PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#115    _drawFrame (dart:ui/hooks.dart:115:31)
代码语言:javascript
复制
代码语言:javascript
复制

为了解决这个问题,我需要通过其构造函数将小部件属性向下传递到小部件状态:

lib/presentation/widgets/type_error_workaround.dart

代码语言:javascript
复制
...
@override
  State<TypeWorkaroundWidget> createState() => _TypeErrorWidgetState<T>(
        idMapper: idMapper,
      );

...

class _TypeErrorWidgetState<T> extends State<TypeWorkaroundWidget> {
  late List<String> _itemsIds;
  final IdMapper<T> idMapper;

  _TypeErrorWidgetState({
    required this.idMapper,
  });

  @override
  void initState() {
    _itemsIds = widget.items.map((e) {
      return idMapper(e) <-- it won't throw;
    }).toList();
    super.initState();
  }

除了我已经找到了解决办法的这个问题之外,我还有一个类似的问题,在本例中,我使用的是Freezed类型类:

lib/utils/types/freezed_example_type.dart

代码语言:javascript
复制
@freezed
class FreezedExampleType<T extends Object> with _$ExampleClass<T> {
  factory FreezedExampleType.example({
    required TypedFnExample<T> callback,
  }) = _Example<T>;
}

typedef TypedFnExample<T> = String Function(T item);

其思想是,稍后我可以将许多FreezedExampleType实例推到数组中,然后我可以根据类类型将一些逻辑放入其中,在我的示例中,我只通过按一个项简化了这一点:

代码语言:javascript
复制
class FreezedPage extends StatefulWidget {
  const FreezedPage({super.key});

  @override
  State<FreezedPage> createState() => _FreezedPageState();
}

class _FreezedPageState extends State<FreezedPage> {
  bool _makeItCrash = false;
  bool _makeItWork = false;

  List<FreezedExampleType> exampleType = List<FreezedExampleType>.of([]);

  @override
  void initState() {
    exampleType.add(
      FreezedExampleType<ExampleListItem>.example(
        callback: (item) {
          return item.id;
        },
      ),
    );
    super.initState();
  }
...

稍后,我们访问数组上的类型并尝试对它的类型化属性采取行动:

代码语言:javascript
复制
_userType() {
    const item = ExampleListItem(
      id: "exampleId",
      title: "Example Title",
    );
    print(
      exampleType.first.mapOrNull(
        example: (value) {
          return value.callback(item); <- This will throw! =c
        },
      ),
    );
  }

不幸的是,这会引发相同类型的错误:type '(ExampleListItem) => String' is not a subtype of type '(Object) => String'

代码语言:javascript
复制
Logs      ```   type '(ExampleListItem) => String' is not a subtype of type '(Object) => String' 

当抛出异常时,这是堆栈:#0 _FreezedPageState._userType。(package:type_issues/presentation/pages/freezed_example_page.dart:86:24) #1 _$_Example.mapOrNull (package:type_issues/utils/types/freezed_example_type.freezed.dart:198:21) #2 _FreezedPageState._userType (package:type_issues/presentation/pages/freezed_example_page.dart:84:25) #3 _FreezedPageState.build.(package:type_issues/presentation/pages/freezed_example_page.dart:51:17) #4 _InkResponseState.handleTap #5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24) #6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:627:11) #7 BaseTapGestureRecognizer._checkUp (包装:颤振/src/手势/(package:flutter/src/gestures/recognizer.dart:615:9) #9 PrimaryPointerGestureRecognizer.handleEvent #10 PointerRouter._dispatch PointerRouter._dispatchEventToRoutes #11 PointerRouter._dispatchEventToRoutes。(package:flutter/src/gestures/pointer_router.dart:143:9) #12 _LinkedHashMapMixin.forEach #13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18) #14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7) #15 GestureBinding.handleEvent (包装:颤振/src/手势/binding.dart)::460:19) #16 (package:flutter/src/gestures/binding.dart:440:22) #17 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:337:11) #18 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:395:7) #19 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:357:5) #20 GestureBinding._flushPointerEventQueuesrc/ GestureBinding._handlePointerDataPacket /binding.dart:314:7) #21 GestureBinding._handlePointerDataPacket #22 _invoke1 (飞镖:ui/hooks.dart:167:13) #23 PlatformDispatcher._dispatchPointerDataPacket (飞镖:ui/platform_Dispatcher.dart:341:7) #24 _dispatchPointerDataPacket (飞镖:ui/hooks.dart:94:31)

处理器:"onTap“识别器: TapGestureRecognizer#90ba6

代码语言:javascript
复制
</details>


[1]: https://github.com/flutter/flutter/issues/110718
EN

回答 1

Stack Overflow用户

发布于 2022-08-31 22:19:45

TypeErrorWidget的state类中,将Type设置如下:

代码语言:javascript
复制
class TypeErrorWidget<T> extends StatefulWidget {
  final Iterable<T> items;
  final IdMapper<T> idMapper;

  const TypeErrorWidget({
    Key? key,
    required this.items,
    required this.idMapper,
  }) : super(key: key);

  @override
  State<TypeErrorWidget<T>> createState() => _TypeErrorWidgetState<T>();
}

class _TypeErrorWidgetState<T> extends State<TypeErrorWidget<T>> {
  late List<String> _itemsIds;

  @override
  void initState() {
    _itemsIds = widget.items.map((e) {
      return widget.idMapper(e);
    }).toList();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text("I'll crash"),
        Text(_itemsIds.toString()),
      ],
    );
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73562391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档