T::Enum は、型に使用された無効な列挙型のエラーを発生させる代わりに、無効な列挙型が使用された場合に初期化されていない定数を発生させます
概要
私たちのアプリでは、ボタン コンポーネントのバリアントに Enum を使用します。
class ButtonComponent
sig do
params(
button_variant: ButtonVariant
).void
end
def initialize(button_variant: ButtonVariant::Primary)
end
列挙型は次のとおりです。
class ButtonComponent
class ButtonVariant < T::Enum
extend T::Sig
enums do
Primary = new
Secondary = new
Tertiary = new
end
sig { returns(String) }
def css_class
case self
when Primary
'btn--primary'
when Secondary
'btn--secondary'
when Tertiary
'btn--tertiary'
else
T.absurd self
end
end
end
end
ここで、無効なオブジェクトを渡すと次のようになります。
render ButtonComponent.new(button_variant: ButtonComponent::UNKNOWN)
Sorbet からは、間違った型が渡されたという素晴らしいエラーが返されます。
Parameter 'button_variant': Expected type ButtonComponent::ButtonVariant
ただし、正しい型を渡しても無効な列挙型を渡した場合は、次のようになります。
render ButtonComponent.new(button_variant: ButtonComponent::ButtonVariant::UNKNOWN)
定数が不明であるというエラーのみが表示されます。
uninitialized constant ButtonComponent::ButtonVariant::UNKNOWN
Sorbet は、初期化されていない定数に関するより一般的なエラーをスローするのではなく、列挙型が無効であるというエラーを生成するべきではないでしょうか?
私たちは、開発者にとって何が問題なのかが明らかになるように、エラーがより明確になることを期待していました。 ButtonComponent::ButtonVariant 型に無効な ‘enum’ が使用されました。列挙型を間違って使用したのでしょうか、それともこれは Sorbet で予期された動作なのでしょうか?
解決策
この小さな例は次のとおりです (sorbet.run を参照)。
# typed: true
class Foo < T::Enum
enums do
BAR = new('bar')
end
end
Foo::BAR
Foo::Zoo
# ^ Unable to resolve constant Zoo https://srb.help/5002
2023 年 9 月 11 日の時点では、Sorbet はこれを未解決の定数と見なしているため、これは予想される動作です。
sorbet の GitHub で問題を報告すると、修正が検討されるか、修正できない理由についてのより詳細な説明が得られます。