How to type a union of constants

Viewed 351

I would like to do the following:

from typing import Union, Literal
YES = 1
NO = 0
ValidResponse = Union[Literal[YES], Literal[NO]]

Of course, Python won't let me do this because YES and NO are considered to be variables, not literal numbers.

Obviously I can do ValidResponse = Union[Literal[1], Literal[0]], but as a programmer editing this file later, it seems odd that in order to change what constant YES used (for example YES = 'yes'), I would need to change it in two different places.

What's the best way to handle this scenario?

2 Answers

You should almost certainly just be using an enum instead:

import enum

class ValidResponse(enum.Enum):
    YES = 1
    NO = 0

Now you can use ValidResponse as an annotation:

def foo(response: ValidResponse) -> whatever:
    # do something with response

The enum solution is often the cleaner solution in these situations, but note that it is possible to do this kind of thing with typing.Literal. You have to explicitly annotate your variables as being of a "literal" type. The YesType and NoType aliases that I've introduced aren't strictly necessary, but may be helpful for clarity:

from typing import Union, Literal

YesType = Literal[1]
NoType = Literal[0]

YES: YesType = 1
NO: NoType = 0

ValidResponse = Union[YesType, NoType]
Related