为何Dart泛型T无法被推断为非可空类型?代码问题咨询
泛型类与非可空类型推断差异解析
问题场景
报错的泛型代码
abstract class Foo<T> { Future<T?> read(String id); Future<T> createModel(String id); Future<T> readOrCreateModel(String id) async { T? model = await read(id); model ??= await createModel(id); return model; } }
这段代码中readOrCreateModel方法会触发类型错误:‘T?’类型的值无法返回,因为方法返回类型为‘Future<T>’。
正常运行的非泛型代码
abstract class Foo { Future<int?> read(String id); Future<int> createModel(String id); Future<int> readOrCreateModel(String id) async { int? model = await read(id); model ??= await createModel(id); return model; } }
非泛型版本中类型推断完全正常,没有报错。
原因解析
Dart的泛型参数默认是可空/非可空兼容的,也就是说Foo<T>中的T可以是任意类型,包括可空类型(比如T=int?)。
当T是可空类型时,createModel方法返回的Future<T>本质是Future<可空类型>,这时候model ??= await createModel(id)无法保证model最终是非空的——如果createModel返回的也是null(因为T本身允许为空),model依然是null,不符合Future<T>的返回要求(Dart类型检查不会默认假设T是非可空的)。
而非泛型版本里,int是明确的非可空类型,createModel返回的Future<int>必然是非空值,所以model ??= ...执行后,model肯定是有效的非空int,可以安全返回给Future<int>类型的方法。
解决办法
给泛型参数T加上非可空约束,限定T只能是非可空类型:
abstract class Foo<T extends Object> { Future<T?> read(String id); Future<T> createModel(String id); Future<T> readOrCreateModel(String id) async { T? model = await read(id); model ??= await createModel(id); return model; } }
通过T extends Object约束,T被限定为非可空类型,此时createModel返回的Future<T>一定是非空值,model经过??=赋值后必然是非空的T,类型检查就能通过。
内容的提问来源于stack exchange,提问作者TSR
相关产品推荐
相关产品推荐

