Closed
Description
Dart version: Dart SDK version: 2.16.2 (stable) (Tue Mar 22 13:15:13 2022 +0100) on "macos_x64"
Error reproducible with the below sample on DartPad.
The type inferer doesn't report a Function
typing error and fails at runtime instead. Consider the sample below:
typedef Json = Map<String, dynamic>;
abstract class Entity {}
class EntityMapper<T extends Entity> {
// Generated with json_serializable.
final Json Function(T) toJson;
final T Function(Json) fromJson;
EntityMapper(this.toJson, this.fromJson);
}
class Repository<T extends Entity> {
// Provides real data from Firestore.
final Iterable<T> Function() _dataProvider;
final EntityMapper<T> mapper;
Repository(this._dataProvider, this.mapper);
Iterable<T> findAll() => _dataProvider();
// Json toJson(T entity) => mapper.toJson(entity);
}
class EntityA extends Entity {}
final entityAMapper = EntityMapper<EntityA>(
(a) => {'name': 'A'},
(json) => EntityA(),
);
class Processor {
final Iterable<Repository<Entity>> _repositories;
Processor(this._repositories);
void process() {
for (final repository in _repositories) {
final entities = repository.findAll();
final entityJsons = entities.map(repository.mapper.toJson); // <<<
// final entityJsons = entities.map(repository.toJson);
for (final entityJson in entityJsons) {
print(entityJson);
}
}
}
}
void main() {
final entityARepository = Repository<EntityA>(
() => [EntityA(), EntityA()],
entityAMapper,
);
Processor([entityARepository]).process();
}
- There is an
Entity
superclass. - There is a generic
EntityMapper
which takes functions mapping to/from JSON to instance. - There is a mapper instance for each
Entity
subclass. - A generic
Repository
is parameterized with a data provider and a mapper for a specificEntity
subclass. - A
Processor
gets a list of repositories, iterates over them, gets all entities and attempts to convert them to JSON.
The line marked with <<<
causes the following failure:
Uncaught Error: TypeError: Closure 'entityAMapper_closure': type '(EntityA) => Map<String, dynamic>' is not a subtype of type '(Entity) => Map<String, dynamic>'
This happens only at runtime and the type inferer / analyzer aren't able to report this issue before that.
When the commented out method Repository.toJson
is enabled, which basically just delegates a method call to the mapper, and the Processor
is updated by now using the new Repository.toJson
method, the code works fine.
- Should type inference be able to find the issue with the original code?
- Why doesn't the code work in the first place?
- Why does simple delegation fix the error?
Metadata
Metadata
Assignees
Labels
No labels