PEP: https://peps.python.org/747
Реализация: https://github.com/python/cpython/pull/145034
Что и зачем?
Представьте, что вам нужно описать, что какая-то функция может принять в качестве входного аргумента любую аннотацию. Например для валидации как в пидантике. Как бы вы такое сделали?
type[T]?
from typing import Any
def validate[T](typ: type[T], value: Any) -> None: ...
validate(int, 1)
Но, на самом деле у нас тут есть ошибка.
typ будет ожидать любой объект класса type, а не любую аннотацию.Например,
int | str не является объектом класса type, но является валидной аннотацией. Так же как и: None, Literal[1], Self, T, тд.Пример в pyright.
Данная фича реально нужна авторам библиотек, кто строит свою логику работы на типах.
Реальный пример: в django-modern-rest (нативная интеграция 🌚️️️️) мы создаем метаданные об ответе
ResponseSpec(return_type=int | str, status_code=200) для такого кода пользователя:
from dmr import Controller
from dmr.plugins.msgspec import MsgspecSerializer
class UserController(Controller[MsgspecSerializer]):
async def get(self) -> int | str: ...
На данный момент
ResponseSpec.return_type имеет аннотацию Any, как единственный рабочий вариант. Но в идеале мы будем использовать
TypeForm[Any] в ближайшее время.Как и многие другие:
• pydantic
• msgspec
• dishka (использует аннотации для DI)
• Даже некоторые места stdlib, например: dataclasses.fields
Итоговый пример:
from typing_extensions import TypeForm, Any
def validate[T](typ: TypeForm[T], value: Any) -> T: ...
reveal_type(validate(int, 1)) # int
reveal_type(validate(int | str, 1)) # int | str
Текущее состояние
В
typing_extensions код уже есть, поддержка в mypy будет в версии 1.20 (следующей).В pyright поддержка уже есть полтора года как.
В Python3.15 будет нативно в
typing. Еще одна хорошая фича.
Обсуждение: какие варианты использования
TypeForm есть у вас? | Поддержать | YouTube | GitHub | Чат |