添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Dart value becomes dynamic during runtime. Causing TypeError: type is not a subtype of dynamic (type comes from generics)

Ask Question

I have a function that creates a value of a generic type. When I pass that value to another function within the same class that expects that generic type, dart throws TypeError: Closure 'closure3': type '(int) => String' is not a subtype of type '(dynamic) => String' where int is an example of a possible generic type.

My real code is too large but I made a simplified version on dartpad.dev that illustrates the exact problem:

class Example<T> {
  final String identifier;
  final T Function(/*params*/) createModel; // for example purposes
  final String Function (T t) buildForModel; 
  Example({ this.identifier, this.createModel, this.buildForModel });
final Example<int> foo1 = Example(
  identifier: 'foo1',  
  createModel: () => 10,
  buildForModel: (i) => 'My widget from $i',
final Example<String> foo2 = Example(
  identifier: 'foo2',  
  createModel: () => 'some model',
  buildForModel: (s) => 'My widget from $s',
final Example<double> foo3 = Example(
  identifier: 'foo3',  
  createModel: () => 10.0,
  buildForModel: (d) => 'My widget from $d',
final List<Example> registry = [
  foo1, foo2, foo3,
Example deserialize(String identifier) {
  return registry.singleWhere((e) => e.identifier == identifier);
// Somewhere else ==================================================
void main() {
  final result = deserialize('foo1');
  final model = result.createModel(); // becomes dynamic!
  print(result.buildForModel(model)); // throws int is not a subtype of dynamic

I'm still learning dart and trying to wrap my head around the concept of reified types, but should I just refactor all my code to find another way to serialize my widget "factories" that doesn't involve iterating a list to retrieve a value or is there a way to fix the current problem?

deserialize is declared to return an Example, which is shorthand for Example<dynamic>. Since result is Example<dynamic>, the static type for result.createModel is dynamic Function(), hence it returns dynamic. However, your problem isn't that model is dynamic; it's that result is Example<dynamic>, which you can verify by trying result.buildForModel(10). – jamesdlin Oct 7, 2020 at 16:29

You need to explicitly declare the return type or else dart will assume is of type dynamic .

Example deserialize(String identifier) {
  return registry.singleWhere((e) => e.identifier == identifier);

Here you are supposed to return something with dType as Example, but registry.singleWhere((e) => e.identifier == identifier) is returning your data with the type being dynamic.

Explicitly convert your return like this registry.singleWhere<Example>((e) => e.identifier == identifier) and you will be good to go :)

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.