From 79f2e6af1cdce42374bd2e39f1028d6052d1b902 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Fri, 19 Dec 2025 16:42:22 -0800 Subject: [PATCH] two new typing FAQ entries --- docs/reference/typing-faq.md | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/docs/reference/typing-faq.md b/docs/reference/typing-faq.md index cecb49c..e0bb8e9 100644 --- a/docs/reference/typing-faq.md +++ b/docs/reference/typing-faq.md @@ -251,3 +251,53 @@ No. ty does not have a plugin system and there is currently no plan to add one. We prefer extending the type system with well-specified features rather than relying on type-checker-specific plugins. That said, we are considering adding support for popular third-party libraries like pydantic, SQLAlchemy, attrs, or django directly into ty. + +## Why does ty say I have an invalid method override? + +We plan to [improve the detail](https://github.com/astral-sh/ty/issues/1644) provided by this +diagnostic, so it's easier to identify the root cause. + +One common cause of this error (especially for mypy users) is that a subclass overrides a base class +method and changes the name of a parameter which is not positional-only. For example: + +```py +class Base: + def process(self, data: str) -> None: + ... + +class Derived(Base): + def process(self, info: str) -> None: # error: invalid-method-override + ... + +def use_base(b: Base) -> None: + b.process(data="hello") # Oops +``` + +The last line here will be accepted by a type checker, but if an instance of `Derived` is passed to +`use_base` (which is valid, since `Derived` is a subclass of `Base`), the call will raise an error +at runtime, since `Derived.process` does not have a `data` parameter. + +We may [split this case into a separate diagnostic +code](https://github.com/astral-sh/ty/issues/2073), so that users who want mypy-compatible behavior +can suppress it specifically. + +For safety, ty checks methods for compatibility with all inherited classes, not just the immediate +parent class. This can put you in a situation where you can't avoid this error, because you are +inheriting a library class that already overrides its own base class method incompatibly, and no +matter how you define your override, it will be incompatible with one of the base class methods. We +are considering [trying to avoid the error in this +case](https://github.com/astral-sh/ty/issues/2000). + +## What is `Top[list[Unknown]]`, and why does it appear? + +This type represents "all possible lists of any element type" (as opposed to `list[Unknown]`, which +represents "a list of some unknown element type"). It usually arises from a check such as +`if isinstance(x, list):`. If `x` was previously of type `Item | list[Item]`, you may expect this check +to narrow the type to `list[Item]`, but ty respects the possibility that there could be a common +subclass of both `Item` and `list` (which may not be a list of `Item`!), and so the narrowed type is +instead `(Item & Top[list[Unknown]]) | list[Item]`. This code can be made more robust by instead +checking `if instance(x, Item)`, or by declaring the `Item` type as `@typing.final`. + +See also [discussion +here](https://docs.astral.sh/ty/features/type-system/#top-and-bottom-materializations) and [in this +issue](https://github.com/astral-sh/ty/issues/1578).