I'm trying to write a function for asserting that user input matches a defined Literal type.
Basically, given:
MyLiteral = Literal["foo", "bar"]
I want to write a function that lets me do this:
some_user_provided_value = input() # For examplegood_value = assert_literal(MyLiteral, some_user_provided_value)
The type of good_value
should now be inferred to be MyLiteral
. If the user value didn't match any of the defined literal strings, an assertion error would be raised.
This should have the same effect as:
some_user_provided_value = input() # For examplegood_value: MyLiteralif some_user_provided_value == "foo": good_value = "foo"elif some_user_provided_value == "bar": good_value = "bar"else: raise AssertionError(f"Value {some_user_provided_value!r} is not a MyLiteral")
This is a pattern that is often repeated in my project, so I would like to wrap it up in a function.
The function would look something like this:
from typing import Any, TypeVarT = TypeVar("T")def assert_literal(literal_type: T, value: Any) -> T: if value not in typing.get_args(literal_type): raise AssertionError(f"Value {value!r} is not a {literal_type!r}") return typing.cast(T, value)
This doesn't work, of course, because this function currently wants an instance of type T
and it'll output an instance of type T
.
If I was dealing with regular classes, I could make the parameter type Type[T]
, but this explodes in my face when I use Literal types, presumably because "foo"
is not an instance of MyLiteral
, that doesn't even make any sense.
Is there currently any way to achieve what I'm trying to do? Can Literals
even be mixed with TypeVar
s?