T::Enum raises uninitialized constant if invalid enum used instead of raising error of invalid enum used for type

78 Views Asked by At

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?

1

There are 1 best solutions below

0
marianosimone On BEST ANSWER

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.