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

如何用Sorbet定义类似TS/Rust的泛型Result结构体?

在Sorbet中实现泛型Result联合类型

可以实现你想要的泛型Result类型,无需给Success和Failure类添加多余的泛型参数。通过Sorbet的泛型类型别名,就能封装Success[T] | Failure[E]的联合类型,实现类似Result[T, E]的简洁写法。

实现方案

保留你现有Success和Failure泛型类的基础上,定义一个泛型类型别名Result来封装联合类型:

# typed: strict
# frozen_string_literal: true

module Core
  module Type
    class Success
      extend T::Sig
      extend T::Generic

      ValueType = type_member

      sig { returns(ValueType) }
      attr_reader :value

      sig { params(value: ValueType).void }
      def initialize(value)
        @value = value
      end
    end

    class Failure
      extend T::Sig
      extend T::Generic

      ErrorType = type_member

      sig { returns(ErrorType) }
      attr_reader :error

      sig { params(error: ErrorType).void }
      def initialize(error)
        @error = error
      end
    end

    # 定义泛型Result类型别名,封装Success和Failure的联合类型
    Result = T.type_alias do
      T::Generic.type_parameters(:T, :E) do |T, E|
        T.any(Success[T], Failure[E])
      end
    end
  end
end

extend T::Sig

# 直接使用Result[T, E]作为返回类型,符合你的目标写法
sig { params(value: Integer).returns(Core::Type::Result[Integer, String]) }
def zero?(value)
  if value.zero?
    Core::Type::Success.new(value)
  else
    Core::Type::Failure.new("It is not zero")
  end
end

result = zero?(0)
case result
when Core::Type::Success
  p result.value # Sorbet可正确推断value为Integer类型
when Core::Type::Failure
  p result.error # Sorbet可正确推断error为String类型
end

方案说明

  • 避免了dry-monads中给Success/Failure强制添加双泛型参数的hack写法,保持类的单一职责:Success仅关注成功值类型,Failure仅关注错误类型。
  • 泛型类型别名Result接收两个类型参数T(成功值类型)和E(错误类型),内部直接映射为对应泛型实例的联合类型。
  • Sorbet对该写法完全支持,类型检查和分支推断均能正常工作,比如case分支中会自动识别对应类型的属性类型。

内容的提问来源于stack exchange,提问作者Rostislav Zhuravsky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:20:36