You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart泛型函数能否仅指定部分类型参数实现tryOrNull封装

问题描述

我尝试将「检测指定异常、若抛出该异常则返回null」的逻辑抽取为通用函数,初始实现代码如下:

T? tryOrNull<TException, T>(T Function() innerFunction) {
  try {
    return innerFunction();
  } on TException {
    return null;
  }
}

// 用法示例
DateTime? parseDate(String date) {
  return tryOrNull<FormatException, DateTime>(() => DateTime.parse(date));
}

核心疑问

是否可以通过某种方式定义tryOrNull函数,无需手动指定第二个类型参数(即上述示例中的DateTime)?

我期望的调用形式如下,在我看来DateTime类型完全可以通过传入的innerFunction的返回值类型自动推断,无需手动声明:

// 期望用法
DateTime? parseDate(String date) {
  return tryOrNull2<FormatException>(() => DateTime.parse(date));
}

换言之,如何更优雅地指定需要捕获的异常类型?我希望实现类似Scala中Try(innerFunction).toOption的效果,但适配Dart的空安全特性(在我看来相比Option类型,Dart空安全使用起来更便捷)。

解决方案

Dart 截至3.x稳定版存在一个语言层面的限制:泛型函数调用时如果显式传入任意类型参数,就必须传入全部类型参数,不支持剩余参数自动推断,因此无法直接在原函数签名上实现你期望的单类型参数调用效果。

可以通过一个轻量的中间持有类拆分类型参数的指定时机,实现接近预期的调用效果,代码如下:

// 同步逻辑处理类
class _TryOrNullHandler<TException extends Object> {
  const _TryOrNullHandler();

  T? call<T>(T Function() innerFunction) {
    try {
      return innerFunction();
    } on TException {
      return null;
    }
  }
}

// 异步逻辑处理类
class _TryOrNullAsyncHandler<TException extends Object> {
  const _TryOrNullAsyncHandler();

  Future<T?> call<T>(Future<T> Function() innerFunction) async {
    try {
      return await innerFunction();
    } on TException {
      return null;
    }
  }
}

/// 捕获同步逻辑指定异常,异常时返回null
final tryOrNull = <TException extends Object>() => _TryOrNullHandler<TException>();

/// 捕获异步逻辑指定异常,异常时返回null
final tryOrNullAsync = <TException extends Object>() => _TryOrNullAsyncHandler<TException>();

调用方式

使用时只需要在指定异常类型后多写一对空括号,返回值类型会自动从传入的逻辑推断,无需手动声明:

DateTime? parseDate(String date) {
  // 自动推断返回值为DateTime?,无需手动指定第二个类型参数
  return tryOrNull<FormatException>()(() => DateTime.parse(date));
}

// 异步用法示例
Future<DateTime?> parseDateAsync(String date) async {
  return tryOrNullAsync<FormatException>()(() async {
    final res = await someAsyncParseOperation(date);
    return res;
  });
}

注:给TException添加extends Object约束是为了符合Dart语法要求:on关键字后不允许跟随可空类型。

内容的提问来源于stack exchange,提问作者Joe M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 04:24:12