reflex icon indicating copy to clipboard operation
reflex copied to clipboard

Consider converting string Vars with limited options to Enums

Open iron3oxide opened this issue 2 years ago β€’ 2 comments

Right now, there are a lot of Vars that can theoretically be set to any given str, only comments and sometimes the docs denote the set of options that will actually work. While this will probably not lead to any impossible-to-debug errors, it is always better to be explicit and to save the developer some time by preventing typos and invalid options, e.g. when "xs" is not an available size in one component while it is in another.

Enums are made to solve this kind of problem. Sadly the StrEnum type is only available from the standard enum library starting with 3.11, but there are ways around this:

  1. Using a third-party library
  2. Inheriting from str AND enum.Enum (see StackOverflow)
  3. Using public constants and local Union types of those to achieve a similar behaviour

I'd be happy to do this myself as I enjoy these kinds of refactorings. Do you agree with my assessment of the problem? If so, which of the three ways would you prefer?

iron3oxide avatar Mar 31 '23 07:03 iron3oxide

If I take the pc.heading size prop as an example, I would go with something like that :

HEADING_SIZE = SimpleNamespace(
    SMALL="sm",
    MEDIUM="md",
    ...,
    XXXXL="4xl")

Does it match what you have in mind ?

Lendemor avatar Apr 12 '23 21:04 Lendemor

Roughly, I'd have to get more familiar with SimpleNameSpace to answer this definitively. I actually started working on a PR for this but got a bit too carried away when I tried to apply the principle to CSS props (amazing if done correctly but a lot of work), so now I'd have to merge a lot of new commits from main to continue.

My approach was to have a public string enum, e.g. Size which contains every string size used throughout the project and then have narrower Literal Union types to be used for type hints internally, e.g.:

class Size(str, enum.Enum):
    """Every available size option."""

    XXS = "2xs"
    XS = "xs"
    SM = "sm"
    MD = "md"
    LG = "lg"
    XL = "xl"
    XL2 = "2xl"
    XL3 = "3xl"
    XL4 = "4xl"
    XL5 = "5xl"
    XL6 = "6xl"
    FULL = "full"

HeadingSize = Literal[
    Size.XS, Size.SM, Size.MD, Size.LG, Size.XL, Size.XL2, Size.XL3, Size.XL4
]

This way we'd have a simple and uniform API for developers but they'd also be forced to supply a valid Size, whether as enum option or string. If one uses a modern IDE, the valid options should be obvious and any mistake should be highlighted and easy to spot.

iron3oxide avatar Apr 12 '23 21:04 iron3oxide

We're planning to solve this with Literal type annotations in #1864

masenf avatar Sep 27 '23 19:09 masenf