schultek/dart_mappable

Cause `UnresolvedType` is not a subtype of type `T(Generic)` in type cast error

UkiDelly opened this issue · 3 comments

I was trying to use generic to decode the json into a different model depending on the data I received from the network communication. The problem is when it try to decode from json (either string and map), it cause an error of

UnresolvedType is not a subtype of T(Generic type) in type cast

How could I solve this problem?

This is the BaseResponse model that I use to convert the response from the network.

@MappableClass()
final class BaseResponse<T> with BaseResponseMappable {
  const BaseResponse({
    this.success,
    this.error,
  });

  final SuccessModel? success;
  final ErrorModel? error;

  factory BaseResponse.fromJson(Map<String, dynamic> map) => BaseResponseMapper.fromMap(map);

  factory BaseResponse.fromJsonString(String json) => BaseResponseMapper.fromJson(json);
}

And also SuccessModel is using generic too

@MappableClass()
final class SuccessModel<T> with SuccessModelMappable {
  const SuccessModel({
    required this.data,
    required this.resultCode,
    required this.resultMessage,
  });

  final T? data;
  final int resultCode;
  final String resultMessage;

  factory SuccessModel.fromJson(Map<String, dynamic> map) => SuccessModelMapper.fromMap(map);
  factory SuccessModel.fromJsonString(String json) => SuccessModelMapper.fromJson(json);
}

I am using this TermModel to test it

@MappableClass()
final class TermModel with TermModelMappable {
  const TermModel({
    required this.agid,
    this.deleted,
    this.lid,
    required this.name,
    this.cid,
    this.cidName,
    this.content,
    this.sortNo,
    this.required,
    this.requiredName,
    this.modate,
    this.regdate,
    this.isChecked = false,
  });
  final int agid;
  final int? deleted;
  final int? lid;
  final String name;
  final int? cid;
  final String? cidName;
  final String? content;
  final int? sortNo;
  final int? required;
  final String? requiredName;
  final String? modate;
  final String? regdate;
  final bool isChecked;

  factory TermModel.fromJson(Map<String, dynamic> map) => TermModelMapper.fromMap(map);
  factory TermModel.fromJsonString(String json) => TermModelMapper.fromJson(json);
}

This is the code I test

import 'dart:convert';
import 'package:http/http.dart' hide BaseResponse;

Future<void> main(List<String> arguments) async {
  final response = await get(Uri.parse("my server api"));

  // decode to Map
  final encodeBody = jsonDecode(response.body);

  print(encodeBody);
  final res = BaseResponse<List<TermModel>>.fromJson(encodeBody);
  print(res.success);
}

Then this is the output

screenshot_2024 02 08_01-17_PM

Any class used through a generic type must be initialized beforehand.

Do TermModelMapper.ensureInitialized()

In this situation, there is only one TermModelMapper, but if there are more models used as generics, will there be no choice but to hardcode .ensureInitialized() of all models?

Check out https://pub.dev/documentation/dart_mappable/latest/topics/Generics-topic.html#generated-initializer

Unfortunately this can't be done fully automatically since Dart does not have static initialization of classes.