Вот пример:
from django.db import models
# ========== defined in a third-party library ==========
class StructuredCountry:
iso_code: str
...
class CountryField(models.CharField):
# Not shown: the textual value from the database
# is converted to a StructuredCountry object.
pass
# ========== defined in my own code ====================
class MyModel(models.Model):
country = CountryField()
reveal_type(MyModel().country) # ⇒ str
MyModel().country.iso_code # E: Attribute "iso_code" is unknown
< /code>
Для приведенного выше примера я хотел бы иметь возможность: < /p>
Код: Выделить всё
class TypedCountryField(FieldAnnotationMixin, CountryField):
pass
class MyModel(models.Model):
country = TypedCountryField()
reveal_type(MyModel().country) # ⇒ StructuredCountry
MyModel().country.iso_code # ✔
< /code>
До сих пор я придумал следующее (вдохновленное заглушками vscode), которое действительно работает < /em>.if TYPE_CHECKING:
class FieldAnnotationMixin[FieldClassType: type[models.Field], ValueType]:
def __new__(cls, *args, **kwargs) -> FieldClassType: ...
# Class access
@overload
def __get__(self, instance: None, owner: Any) -> Self: ... # type: ignore[overload]
# Model instance access
@overload
def __get__(self, instance: models.Model, owner: Any) -> ValueType: ...
# Non-Model instance access
@overload
def __get__(self, instance: Any, owner: Any) -> Self: ...
else:
class FieldAnnotationMixin[IgnoredT1, IgnoredT2]:
pass
< /code>
Однако я застрял на нулевом бите поля. Для поля, определенного на модели с помощью null = true
@overload
def __new__(cls, *args, null: Literal[False] = False, **kwargs) -> FieldClassType[ValueType]: ...
@overload
def __new__(cls, *args, null: Literal[True] = True, **kwargs) -> FieldClassType[ValueType | None]: ...
< /code>
Я сталкиваюсь с двумя проблемами здесь: < /p>
The Type-Checker (справедливо) жалуется «typevar» тип [FieldClasstype@fieldantationmixin] «не подписан». И я не знаю заранее, является ли стороннее поле общим или нет.>
Подробнее здесь: https://stackoverflow.com/questions/796 ... elds-typed