Go the other way around, and build VALID_ARGUMENTS from Argument:

Argument = typing.Literal['foo', 'bar']
VALID_ARGUMENTS: typing.Tuple[Argument, ...] = typing.get_args(Argument)

I've used a tuple for VALID_ARGUMENTS here, but if for some reason you really prefer a list, you can get one:

VALID_ARGUMENTS: typing.List[Argument] = list(typing.get_args(Argument))

It's possible at runtime to build Argument from VALID_ARGUMENTS, but doing so is incompatible with static analysis, which is the primary use case of type annotations.

Doing so is also considered semantically invalid - the spec forbids parameterizing Literal with dynamically computed parameters. The runtime implementation simply doesn't have the information it would need to validate this. Building VALID_ARGUMENTS from Argument is the way to go.

Answer from user2357112 on Stack Overflow
🌐
Python
typing.python.org › en › latest › spec › literal.html
Literals — typing documentation
variable_annotation: LiteralString def my_function(literal_string: LiteralString) -> LiteralString: ... class Foo: my_attribute: LiteralString type_argument: List[LiteralString] def enforce_literal[T: LiteralString](value: T) -> T: return value
Discussions

Inference on Literal Types - Typing - Discussions on Python.org
@erictraut and I have a disagreement on how objects declared as Literal should be propagated in collections. See pyright does not infer list of Literals, but mypy does · Issue #9491 · microsoft/pyright · GitHub I thought I would ask the community here their opinion, as my colleagues and ... More on discuss.python.org
🌐 discuss.python.org
2
November 22, 2024
Using typing.Literal for choosing from a set of strings
I have defined the following class: from typing import List, Optional, Literal, Union from pydantic import BaseModel, EmailStr class Rating(BaseModel): type: Literal["rating"] name: str class Options(TypedD… More on community.openai.com
🌐 community.openai.com
0
0
November 5, 2024
Unpacking container values to Literal type
Exact Q/A match?: https://stackoverflow.com/questions/64522040/dynamically-create-literal-alias-from-list-of-valid-values More on reddit.com
🌐 r/learnpython
2
1
April 24, 2025
Getting the literal out of a python Literal type, at runtime? - Stack Overflow
>>> from typing import Literal, get_args >>> l = Literal['add', 'mul'] >>> get_args(l) ('add', 'mul') However, I don't think you gain anything by using a Literal for what you propose. ... Sign up to request clarification or add additional context in comments. ... Is that Litera[list...] valid Python? mypy gives me error: Invalid type... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Mypy
mypy.readthedocs.io › en › stable › literal_types.html
Literal types and Enums - mypy 1.20.0 documentation
list_of_ints = [] list_of_ints.append(a) reveal_type(list_of_ints) # Revealed type is "list[int]" # But if the variable you're appending is an explicit Literal, mypy # will infer list[Literal[19]]. list_of_lits = [] list_of_lits.append(b) reveal_type(list_of_lits) # Revealed type is "list[Literal[19]]" We can use Literal types to more precisely index into structured heterogeneous types such as tuples, NamedTuples, and TypedDicts. This feature is known as intelligent indexing. For example, when we index into a tuple using some int, the inferred type is normally the union of the tuple item types
🌐
Python.org
discuss.python.org › typing
Inference on Literal Types - Typing - Discussions on Python.org
November 22, 2024 - @erictraut and I have a disagreement on how objects declared as Literal should be propagated in collections. See pyright does not infer list of Literals, but mypy does · Issue #9491 · microsoft/pyright · GitHub I thought I would ask the community here their opinion, as my colleagues and ...
🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
February 24, 2026 - The argument list must be a list of types, a ParamSpec, Concatenate, or an ellipsis (...). The return type must be a single type. If a literal ellipsis ...
🌐
Adam Johnson
adamj.eu › tech › 2021 › 07 › 09 › python-type-hints-how-to-use-typing-literal
Python type hints: how to use typing.Literal - Adam Johnson
September 7, 2021 - Python type hints have no formal specification for exhaustiveness checking yet, but we can emulate it with the NoReturn type. If we use a function that accepts NoReturn as a value type, any call to it will fail, since NoReturn matches no type. This technique was documented for Enum types in a blog post by Haki Benita. We can also use it with Literal types. Imagine we forgot to handle the "chess" case in our get_game_count() function: from typing import Literal, NoReturn def assert_never(value: NoReturn) -> NoReturn: """Exhaustiveness checking failure function""" assert False GameType = Literal["checkers", "chess"] def get_game_count(game: GameType) -> int: if game == "checkers": count = 123 else: assert_never(game) return count
🌐
OpenAI Developer Community
community.openai.com › api
Using typing.Literal for choosing from a set of strings - API - OpenAI Developer Community
November 5, 2024 - I have defined the following class: from typing import List, Optional, Literal, Union from pydantic import BaseModel, EmailStr class Rating(BaseModel): type: Literal["rating"] name: str class Options(TypedDict): color: Literal["yellowBright", "orangeBright", "redBright", "pinkBright", "purpleBright", "blueBright", "cyanBright", "tealBright", "greenBright", "grayBright"] max: int options: Options I assumed that this ...
🌐
Reddit
reddit.com › r/learnpython › unpacking container values to literal type
r/learnpython on Reddit: Unpacking container values to Literal type
April 24, 2025 -

I want to create a type alias for a Literal type from the values of a container (list, tuple, members of an Enum, whatever). This would be nice and DRY as the type could inherit the values of the container as my developing API evolves.

My only issue is that MyPy doesn't appreciate it (Invalid type alias: expression is not a valid type [valid-type]). But I'm inclined to say yeet and go with it. Thoughts?

from typing import Literal

modes = ("r", "w", "a")

# The WET (write everything twice) way
type ModeVals1 = Literal["r", "w", "a"]

# The DRY (don't repeat yourself) way
type ModeVals2 = Literal[*modes]
# functionally equivalent right?


# In use
def my_func(mode: ModeVals2, ...):
    ...
Find elsewhere
🌐
Medium
medium.com › data-science › python-type-hinting-with-literal-03c60ce42750
Python Type Hinting with Literal. More powerful than it seems: use… | by Marcin Kozak | TDS Archive | Medium
November 28, 2023 - PYTHON PROGRAMMING Python Type Hinting with Literal More powerful than it seems: use typing.Literal to create literal types I’ll admit it: I wasn’t always a fan of typing.Literal, a form of …
🌐
TestDriven.io
testdriven.io › tips › c61d55d8-caa7-4ab4-b611-7356bddc0181
Tips and Tricks - Python type hints - typing.Literal | TestDriven.io
Python tip: You can use Literal to indicate that value can be one of the provided literals. Static type checkers will report an error when the value doesn't match one of the provided literals. https://mypy.readthedocs.io/en/stable/literal_types.html#literal-types · from typing import Literal STATUS = Literal["ACTIVE", "DISABLED"] class User: def __init__(self, username: str, status: STATUS): self.username = username self.status = status user = User("[email protected]", "CREATED") """ mypy example.py example.py:12: error: Argument 2 to "User" has incompatible type "Literal['CREATED']"; expected "Union[Literal['ACTIVE'], Literal['DISABLED']]" Found 1 error in 1 file (checked 1 source file) """ View All Tips ·
🌐
Python
peps.python.org › pep-0586
PEP 586 – Literal Types - Python Enhancement Proposals
March 14, 2019 - Literal types indicate that some expression has literally a specific value. For example, the following function will accept only expressions that have literally the value “4”: from typing import Literal def accepts_only_four(x: Literal[4]) -> None: pass accepts_only_four(4) # OK accepts_only_four(19) # Rejected
Top answer
1 of 3
78

The typing module provides a function get_args which retrieves the arguments with which your Literal was initialized.

>>> from typing import Literal, get_args
>>> l = Literal['add', 'mul']
>>> get_args(l)
('add', 'mul')

However, I don't think you gain anything by using a Literal for what you propose.

2 of 3
6

I'm working with lots of sets of different characters and character sequences and ended up here.

If you're using type aliases defined using the type statement, get_args doesn't work directly. And a Union of Literals is messy, so the below is what I ended up with:

from collections.abc import Sequence, Iterator
from typing import Literal, get_args, TypeAliasType, cast

def get_literal_vals(alias: TypeAliasType) -> frozenset:
    def val(alias: TypeAliasType):
        return alias.__value__
    def args(alias: TypeAliasType):
        return get_args(val(alias))
    def resolveT -> Iterator[T]:
        if isinstance(alias, TypeAliasType):
            for val in resolve(args(alias)):
                yield from resolve(val)
            return
        if isinstance(alias, tuple):
            t_seq = cast(Sequence[T], alias)
            for element in t_seq:
                yield from resolve(element)
            return
        yield alias
    return frozenset(resolve(alias))

type Doubles = Literal["ab", "de", "gh"]
type Triples = Literal["abc", "def", "ghi"]
type DT = Doubles | Triples
dt_set: frozenset[DT] = get_literal_vals(DT)

This has some type checking issues depending on how strict your type checker is but works in practice:

>>> type Triples = Literal["abc", "def", "ghi"]
>>> get_literal_vals(Triples)
frozenset({'def', 'abc', 'ghi'})
>>> type Doubles = Literal["ab", "de", "gh"]
>>> get_literal_vals(Doubles)
frozenset({'gh', 'de', 'ab'})
>>> type DT = Doubles | Triples
>>> get_literal_vals(DT)
frozenset({'ghi', 'de', 'ab', 'abc', 'gh', 'def'})

An interesting side effect of this is that dynamic user input string values can be constrained to a set of specific literal values within conditional branches.

def foo(bar: str):
    if bar in dt_set:
        # bar is considered a literal value in DT
        # by some type checkers.
        pass
    # bar is an unconstrained string value
    # outside of the conditional branch.
🌐
GeeksforGeeks
geeksforgeeks.org › python › dynamic-testing-of-values-against-python-literal-types
Dynamic Testing of Values Against Python Literal Types - GeeksforGeeks
July 23, 2025 - Literal types in Python allow you to restrict the values of a variable to a specific set. This is done using the Literal type from the typing module.
🌐
Towards Data Science
towardsdatascience.com › home › latest › python type hinting with literal
Python Type Hinting with Literal | Towards Data Science
January 22, 2025 - Hence, unless you’re ready to accept unpredictable behavior of Python, don’t use typing.Literal with generator expressions before this issue is solved. But there’s nothing to worry about, as generator expressions are typically used to overcome memory issues – and creating a literal type doesn’t seem like something that should lead to such problems. Hence, instead of using a generator to create a literal type, you can make a list out of it and use it.
🌐
JetBrains
youtrack.jetbrains.com › issue › PY-38065
Support literal tuples types declared with typing.Literal
May 27, 2021 - {{ (>_<) }} This version of your browser is not supported. Try upgrading to the latest stable version. Something went seriously wrong
🌐
Numba
numba.pydata.org › numba-doc › dev › developer › literal.html
Notes on Literal Types — Numba 0.52.0.dev0+274.g626b40e-py3.7-linux-x86_64.egg documentation
Ensures that the given argument types (in args and kwargs) are literally typed for a function with the python signature pysig and the list of literal argument names in literal_args.
🌐
LWN.net
lwn.net › Articles › 891082
A literal string type for Python [LWN.net]
April 13, 2022 - That works to join the two parameters with a ", " because that separator string is literal, as it is not composed from other strings, and the join() arguments also have the type LiteralString. It might seem like the language is "casting" the value to the return type, but that is not happening here; Python type annotations are not used by the language at run time. That kind of type overloading also applies to f-strings, so those can still produce a LiteralString: def baz(x: List[LiteralString], y: List[LiteralString]) -> LiteralString: xout = " ".join(x) yout = "+".join(y) return f"({xout}) '{yout}'" baz(["a", "b"], ["c", "d"]) # produces "(a b) 'c+d'" as a LiteralString
🌐
Python
peps.python.org › pep-0675
PEP 675 – Arbitrary Literal String Type | peps.python.org
November 30, 2021 - Since we want the sqlite3 execute method to disallow strings built with user input, we would make its typeshed stub accept a sql query that is of type LiteralString: from typing import LiteralString def execute(self, sql: LiteralString, parameters: Iterable[str] = ...) -> Cursor: ...
🌐
Mypy
mypy.readthedocs.io › en › stable › cheat_sheet_py3.html
Type hints cheat sheet - mypy 1.20.0 documentation
# For most types, just use the name of the type in the annotation # Note that mypy can usually infer the type of a variable from its value, # so technically these annotations are redundant x: int = 1 x: float = 1.0 x: bool = True x: str = "test" x: bytes = b"test" # For collections on Python 3.9+, the type of the collection item is in brackets x: list[int] = [1] x: set[int] = {6, 7} # For mappings, we need the types of both keys and values x: dict[str, float] = {"field": 2.0} # Python 3.9+ # For tuples of fixed size, we specify the types of all the elements x: tuple[int, str, float] = (3, "yes