In our app we use an Enum for variant on our button component:
class ButtonComponent
sig do
params(
button_variant: ButtonVariant
).void
end
def initialize(button_variant: ButtonVariant::Primary)
end
The enum is as follows:
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
Now if we pass in an invalid object:
render ButtonComponent.new(button_variant: ButtonComponent::UNKNOWN)
we get a nice error from Sorbet about the incorrect type being passed:
Parameter 'button_variant': Expected type ButtonComponent::ButtonVariant
However if we pass in the correct type, but an invalid enum:
render ButtonComponent.new(button_variant: ButtonComponent::ButtonVariant::UNKNOWN)
We get just an error that the constant is unknown:
uninitialized constant ButtonComponent::ButtonVariant::UNKNOWN
Shouldn't Sorbet be raising an error that the Enum is invalid rather than throwing a much more generic error about uninitialized constants?
We were expecting the errors would be much more explicit so its clear to the developer what's wrong e.g. invalid 'enum' used for type ButtonComponent::ButtonVariant
. Have we use the enum incorrectly or is this expected behaviour in Sorbet?
A smaller example of this is the following (see in 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
As of 2023-09-11, Sorbet considers this an unresolved constant, so this is the expected behavior.
You can report the issue in sorbet's GitHub, and it will either be considered for a fix, or you'll get a more detailed explanation on why this is not fixable.