String lower method does not retain the generic type

Viewed 41
def cart(fruit: Literal["apple", "orange"]):
    print(fruit)


my_fruit = "Apple"

cart(my_fruit.lower()) # <======= SYNTAX ERROR 
Argument of type "LiteralString" cannot be assigned to parameter "fruit" of type "Literal['apple', 'orange']" in function "cart"
  Type "LiteralString" cannot be assigned to type "Literal['apple', 'orange']"
    "LiteralString" cannot be assigned to type "Literal['apple']"
    "LiteralString" cannot be assigned to type "Literal['orange']"

I also tried but got the same error as above:

my_fruit = "Apple"

my_fruit_in_lowercase = my_fruit.lower()

cart(my_fruit_in_lowercase) # <======= SYNTAX ERROR 

Type of my_fruit_in_lowercase is LiteralString when it should be Literal['apple']

1 Answers

The type of lower is

@overload
def lower(self: LiteralString) -> LiteralString: ...
@overload
def lower(self) -> str: ...  # type: ignore[misc]

It takes LiteralString to LiteralString and arbitrary strings to strings. Anything more would be a bizarre special case in the type system. Python's gradual typing rules do not do arbitrary code evaluation, and as well they shouldn't; that's not the domain of a type checker.

Related