Python中TypeScript keyof的等价实现:基于字典生成Literal类型
从字典键生成字面量类型(Python 3.10+等价于TypeScript的
keyof typeof) 在TypeScript中,我们可以通过as const将对象标记为常量,再用keyof typeof提取其键作为字面量类型:
const tastyFoods = { pizza: '🍕', burger: '🍔', iceCream: '🍦', fries: '🍟', taco: '🌮', sushi: '🍣', spaghetti: '🍝', donut: '🍩', cookie: '🍪', chicken: '🍗', } as const; type TastyFoodsKeys = keyof typeof tastyFoods; // 得到类型:"pizza" | "burger" | "iceCream" | "fries" | "taco" | "sushi" | "spaghetti" | "donut" | "cookie" | "chicken"
问题:Python 3.10+中的等价实现
你尝试的代码无法运行,因为Literal需要接收字面量值的元组,而非运行时动态生成的列表——类型检查器无法静态推断列表元素的固定值:
from typing import Literal tasty_foods = { "pizza": '🍕', "burger": '🍔', "iceCream": '🍦', "fries": '🍟', "taco": '🌮', "sushi": '🍣', "spaghetti": '🍝', "donut": '🍩', "cookie": '🍪', "chicken": '🍗', } # 错误写法:Literal不接受动态生成的列表 TastyFoodsKeys = Literal[list(tasty_foods.keys())]
可行的实现方式
方式一:利用Final标记字典,让类型检查器推断字面量键
通过typing.Final标记字典为不可变常量,类型检查器(如pyright、mypy)会将其键识别为固定的字面量集合,随后即可生成对应的Literal类型:
from typing import Final, Literal # 用Final标记字典,确保键不会被修改,让类型检查器推断字面量键 tasty_foods: Final = { "pizza": '🍕', "burger": '🍔', "iceCream": '🍦', "fries": '🍟', "taco": '🌮', "sushi": '🍣', "spaghetti": '🍝', "donut": '🍩', "cookie": '🍪', "chicken": '🍗', } # 将字典键转为元组,生成Literal类型 TastyFoodsKeys = Literal[tuple(tasty_foods.keys())]
方式二:先定义TypedDict,再提取键生成Literal
如果需要更明确的类型定义,可以先通过TypedDict定义字典的键值类型,再从其注解中提取键生成Literal:
from typing import TypedDict, Literal class TastyFoods(TypedDict): pizza: str burger: str iceCream: str fries: str taco: str sushi: str spaghetti: str donut: str cookie: str chicken: str # 从TypedDict的注解中提取键,生成Literal类型 TastyFoodsKeys = Literal[tuple(TastyFoods.__annotations__.keys())]
注意事项
- 上述实现依赖类型检查器的静态分析能力,推荐使用pyright或mypy来验证类型;
- Python 3.11及以上版本对字面量推断的支持更完善,配合新版本类型检查器效果更好。
内容的提问来源于stack exchange,提问作者brandonscript
相关产品推荐
相关产品推荐

