Python中是否存在TypeScript的Omit类型的等价实现?
Python中是否存在TypeScript的Omit类型的等价实现?
好问题!我之前也纠结过这个——Python标准库在3.12版本之前确实没有像TypeScript那样开箱即用的Omit类型,但我们有几种完全不影响运行时的方法来实现相同的类型约束效果,刚好符合你说的typing.Protocol可行、子类型不行的要求~
一、Python 3.12及以上:直接用官方的typing.Omit
Python 3.12终于跟进了TypeScript这类静态类型语言的常用类型工具,官方新增了typing.Omit,用法和TypeScript几乎一模一样,而且完全是类型层面的操作,不会对运行时产生任何影响:
from typing import TypedDict, Omit # 对应你TypeScript里的Todo接口 class Todo(TypedDict): title: str description: str completed: bool createdAt: int # 就像TS里的Omit<Todo, "description">,直接剔除指定字段 TodoPreview = Omit[Todo, "description"] # 使用起来和TS完全一致,类型检查器会自动验证字段是否符合 todo: TodoPreview = { "title": "Clean room", "completed": False, "createdAt": 1615544252770 }
二、Python 3.11及以下:用Protocol模拟Omit效果
如果你的项目还在用3.12以下的Python版本,官方没有Omit,那我们可以用typing.Protocol来实现完全等价的类型约束,而且完全符合你“不能用子类型”的要求——因为Protocol是基于结构类型的,不是通过继承实现的:
from typing import Protocol, TypedDict class Todo(TypedDict): title: str description: str completed: bool createdAt: int # 我们直接定义一个只包含需要字段的Protocol,相当于手动实现Omit<Todo, "description"> class TodoPreview(Protocol): title: str completed: bool createdAt: int # 使用示例,类型检查器会确保返回的对象结构符合TodoPreview的要求 def get_simplified_todo() -> TodoPreview: return { "title": "Clean room", "completed": False, "createdAt": 1615544252770 }
这里的TodoPreview不需要继承Todo,只要某个对象拥有title、completed、createdAt这三个字段,类型检查器就会认为它符合TodoPreview的要求,完全和TypeScript的Omit效果一致,而且完全不影响运行时的代码逻辑。
额外小技巧:用第三方库提前享受Omit
如果你不想手动写Protocol,也可以用typing_extensions这个官方维护的第三方库,它在Python 3.12之前就提供了Omit类型,用法和官方3.12的Omit完全一样:
from typing_extensions import Omit, TypedDict class Todo(TypedDict): title: str description: str completed: bool createdAt: int TodoPreview = Omit[Todo, "description"]
这个库是Python官方团队维护的,稳定性很高,不用担心兼容性问题。
总结一下:不管你用哪个Python版本,都能实现和TypeScriptOmit完全等价的类型约束,而且所有实现都是纯类型层面的操作,完全不会修改运行时行为,完美贴合你的需求~




