我有一个 Python
Literal
类型,其中包含各种句点分隔的字符串。我还想有一个 Literal
类型,它包含相同的字符串但没有第一个以句点分隔的部分。我可以手动执行此操作,但我不想每次需要删除部分时都这样做。
from typing import Literal
# Period-delimited string literals
ActiveState = Literal['active.green', 'active.yellow', 'active.red']
State = ActiveState | OtherState | AnotherState # I'd like to do this with multiple
# Remove the first period-delimited section for when we're only looking at stuff after that
def handle_active_state(substate: Literal['green', 'yellow', 'red']) -> None: ...
我试过使用
typing.get_args
来迭代和修改 ActiveState
中的值,但是我无法找到在新的 Literal
类型中使用这些值的方法。我尝试使用 types.GenericAlias
重新创建 Literal
,但当我尝试使用它时,它认为结果是一个值而不是类型或类型别名。
from typing import Literal, get_args
from types import GenericAlias
ActiveState = Literal['active.green', 'active.yellow', 'active.red']
ActiveSubstate = GenericAlias(Literal, tuple('.'.join(state.split('.')[1:]) for state in get_args(ActiveState)))
# While this does generate Literal['green', 'yellow', 'red'], it's not usable
def handle_active_state(substate: ActiveSubstate) -> None: ...
# pylance: Illegal type annotation: variable not allowed unless it is a type alias
# Also encountered similar issue with mypy
我的目标是能够制作某种可自动执行此操作的可重用类型。例如,像
Substate[ActiveState]
这样的东西是理想的。这在 Python 中可能吗?如果不是,为什么不可能?
这是为了静态类型分析。这种静态类型分析也适用于其他一些语言。 这个在 TypeScript 中工作的例子:
type ActiveState = 'active.green' | 'active.yellow' | 'active.red';
type Substate<T> = T extends `${infer First}.${infer After}` ? After : T;
type ActiveSubstate = Substate<ActiveState>;
const good: ActiveSubstate = 'green';
const bad: ActiveSubstate = 'blue'; // As expected: Type '"blue"' is not assignable to type 'ActiveSubstate'.