flutter Dart未正确推断泛型类型

dgiusagp  于 2023-11-21  发布在  Flutter
关注(0)|答案(1)|浏览(154)

在下面的代码中,我期望在await postApi(payload, api);处出现错误,因为payload应该是Foo的示例,而不是String,但Dart没有抱怨。类MyRequest在后端和前端之间共享以避免bug,但如果编译器没有抱怨,它就没用了。如何才能使其工作?(可能是Dart中的另一个bug,但是有没有变通方法或调整方法来使它工作?)

typedef JsonMap = Map<String, dynamic>;

enum ApiRoutes {
  nextDuel,
}

abstract class BaseRequestResponse<I, O> {
  ApiRoutes get api;
  I fromJsonReq(JsonMap json);
  JsonMap toJsonRes(O model);
  O fromJsonRes(JsonMap json);
  JsonMap toJsonReq(I model);
}

class Foo {}

class Bar {}

class MyRequest extends BaseRequestResponse<Foo, Bar> {
  @override
  ApiRoutes get api => ApiRoutes.nextDuel;

  @override
  Foo fromJsonReq(JsonMap json) {
    return Foo();
  }

  @override
  Bar fromJsonRes(JsonMap json) {
    return Bar();
  }

  @override
  JsonMap toJsonReq(Foo model) {
    return {};
  }

  @override
  JsonMap toJsonRes(Bar model) {
    return {};
  }
}

Future<O> postApi<I, O>(I payload, BaseRequestResponse<I, O> api) async {
  return api.fromJsonRes({});
}

void main() {
  callApi();
}

Future<Bar> callApi() async {
  final String payload = 'wrong';
  final api = MyRequest();
  final data = await postApi(payload, api);
  return data;
}

字符串

wfveoks0

wfveoks01#

当使用I的两个不同候选类型调用postApi时,(StringFoo),I被推断为它们最近的公共基类型,即Object。因此,postApi调用被推断为postApi<Object, Bar>。这是一个有效的推断,(您可以通过将print('I: $I, O: $O')添加到postApi的主体中来验证这是发生的事情。)
如果你不想在每个调用位置都显式指定类型参数,一种约束postApi的方法是将调用分开,这样I必须首先从一个参数确定。例如:

class PostApi<I, O> {
  final BaseRequestResponse<I, O> api;

  PostApi(this.api);

  Future<O> apply(I payload) async {
    return api.fromJsonRes({});
  }
}

Future<Bar> callApi() async {
  final String payload = 'wrong';
  final api = MyRequest();
  final data = await PostApi(api).apply(payload);
  return data;
}

字符串
这会生成一个错误消息:
无法将参数类型“String”分配给参数类型“Foo”。
但是当payloadFoo的instance时有效。

相关问题