Python type hinting for upper vs lower-cased strings?

Solution 1:

You can in Python 3.10 using typing.TypeGuard.

from typing import TypeGuard


class LowerStr(str):
    '''a dummy subclass of str, not actually used at runtime'''


def is_lower_str(val: str) -> TypeGuard[LowerStr]:
    return val.islower()


l: list[LowerStr] = []


def append(lst: list[LowerStr], v: str):
    if not is_lower_str(v):
        raise TypeError('oh no')
    lst.append(v)

You could indeed enforce runtime safety using a subclass of str. The disadvantage would mostly be performance. You would want to take care to not add an unnecessary __dict__, by adding __slots__ = () to the class definition, from the top of my head.

Either way, string literals are not going to be validated automatically, so it will cause some overhead, either by calling the typeguard, passing them to the constructor of the subtype, or using cast(LowerStr, 'myliteral').