Narrowing types with get_args

Should it be possible to use get_args on literals for type narrowing?
I tried it in Pyright but it doesn’t seem to work.
Seems like a useful feature to have.

I’m sure it seems obvious to you but I have no idea what you are asking/suggesting.

Maybe demonstrate what you mean by showing some code that doesn’t type check and explaining what you want to a type checker to do.

Sorry for not being clear.
I was thinking about something like:

from typing import Literal, TypeAlias, get_args, reveal_type

Alphabet: TypeAlias = Literal['a', 'b', 'c']

def get_x() -> str:
    return 'a'
x = get_x()
if x in get_args(Alphabet):
    # it would be great if the inferred type of `x` was Alphabet as opposed to str
    print(reveal_type(x))
else:
    print(reveal_type(x))

The following seems to work:

from typing import Literal, TypeAlias, TypeIs, get_args, reveal_type

Alphabet: TypeAlias = Literal['a', 'b', 'c']

def is_alphabet(a: str) -> TypeIs[Alphabet]:
    return a in get_args(Alphabet)

def get_x() -> str:
    return 'a'

x = get_x()
if is_alphabet(x):
    print(reveal_type(x))

But it would be nice for it to work without the need of wrapping the check into a TypeIs. Not sure if it’s possible.

Keep in mind that your is_alphabet example won’t work anymore at runtime once you add either a Union, Annotated, or a TypeAliasType in the mix, even though static type-checkers would consider it equivalent.

All these reasons are why I’m not satisfied with this solution.

1 Like

You can do it like this:

Alphabet: TypeAlias = Literal[...]
alphabet: tuple[Alphabet, ...] = get_args(Alphabet)

x = str("a")
reveal_type(x)
if x in alphabet:
    reveal_type(x)