You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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,只要某个对象拥有titlecompletedcreatedAt这三个字段,类型检查器就会认为它符合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完全等价的类型约束,而且所有实现都是纯类型层面的操作,完全不会修改运行时行为,完美贴合你的需求~

火山引擎 最新活动