Typing¶
The package is typed end to end: mypy strict and pyright strict pass, and a test forbids
typing.Any in the source. Opaque values are object, so nothing is silently untyped.
What you get¶
- Options are
TypedDicts. A typo likesummry=is a type error, not a silent no-op.OperationOptions,ControllerOptionsandRouteOptionsare the three layers. - Generic arguments are the configuration.
CRUDController[Post, PostOut, PostIn]is checked, andInstance[Post]isPostat type-check time. - Typed users.
AuthedRequest[User]has.auth: User;current_user(request, User)returnsUser.request.authwithout the helper isobject. - Container keys are
Callable[..., T]. Abstract classes and protocols work without# type: ignore; implementations are checked against the port. - Injection is transparent.
Inject[T]andAnnotated[T, Resolve(fn)]expose the resolved type to the operation signature. - Negative checks are enforced.
tests/typing/check_public_api.pyhas positive and negative cases; an unused# type: ignorefails the suite.
Check your project¶
For model field types in your own code, enable the django-stubs mypy plugin (see
examples/blog/mypy.ini):
[mypy]
plugins = mypy_django_plugin.main
strict = true
[mypy.plugins.django-stubs]
django_settings_module = config.settings
Pitfalls¶
requestis a parameter, notself.request. A missingrequestannotation is an error.- Class attributes are
ClassVar; an operation method is an instance method. - Returning
Status[Model]from a custom action needs the status annotation, e.g.-> Status[Post]; the declaredresponse={201: PostOut}is not inferred from the body. - Under strict mode, passing
objectwhere a model is expected is an error; narrow withisinstanceor annotate the source, rather than casting.