Skip to content

Conversation

@JacobCoffee
Copy link
Member

@JacobCoffee JacobCoffee commented Nov 26, 2025

Description

  • Swap mypy/pyright for ty

241 initial ty diagnostics are suppressed via config to help gradually migrate. Someone can pick this up and run with it to see how it goes.

ty Diagnostics Report (i didnt make this)

Total: 240 diagnostics (without suppressions)

Summary by Rule

Rule Count Severity
invalid-key 52 error
invalid-type-form 51 error
invalid-argument-type 50 error
no-matching-overload 29 error
invalid-assignment 11 error
call-non-callable 10 error
invalid-return-type 9 error
possibly-missing-attribute 9 warning
unresolved-import 6 error
unresolved-attribute 6 error
deprecated 3 warning
unsupported-base 1 warning
redundant-cast 1 warning
not-iterable 1 error
missing-typed-dict-key 1 error

Details by Category

invalid-key (52 errors)

TypedDict key errors - mostly ASGI scope/event types with keys ty doesn't recognize.

Common patterns:

  • Unknown key "status" for TypedDict WebSocketSendEvent
  • Unknown key "body" for TypedDict HTTPResponseStartEvent
  • Unknown key "method" for TypedDict WebSocketScope

Root cause: ty's typeshed stubs for ASGI types may be incomplete or differ from runtime behavior.


invalid-type-form (51 errors)

Invalid type annotations that ty doesn't understand.

Common patterns:

  • Literal[struct_info.tag] - dynamic Literal values
  • Subscripting list method return type
  • TypeVar bounds with string forward references

Root cause: Some advanced typing patterns not yet supported by ty.


invalid-argument-type (50 errors)

Function argument type mismatches.

Common patterns:

  • object passed where specific type expected (after isinstance narrowing)
  • Union types not narrowed correctly
  • Generic type parameter mismatches

Root cause: ty's type narrowing may be less sophisticated than mypy/pyright.


no-matching-overload (29 errors)

No overload signature matches the call.

Common patterns:

  • ResponseHeader(name=..., value=...)
  • Decorator calls with complex signatures
  • Generic class instantiation

Root cause: Overload resolution differences from mypy/pyright.


invalid-assignment (11 errors)

Type mismatch in variable assignments.

Common patterns:

  • Dict literals assigned to TypedDict types
  • Union type assignments

call-non-callable (10 errors)

Calling objects ty thinks aren't callable.

Common patterns:

  • Route handler decorators (HTTPRouteHandler, WebsocketRouteHandler)
  • Router class

Root cause: ty may not recognize callable protocols or __call__ methods.


invalid-return-type (9 errors)

Return type doesn't match declared type.

Common patterns:

  • Implicit None returns
  • Template return types

unresolved-import (6 errors)

Cannot resolve imported module.

Affected modules:

  • litestar.plugins.sqlalchemy (external package)
  • picologging (optional dependency)
  • exceptiongroup (Python 3.11+ backport)

unresolved-attribute (6 errors)

Attribute access on objects ty can't resolve.

Common patterns:

  • BaseException.extra, BaseException.detail
  • Sphinx BuildEnvironment custom attributes

deprecated (3 warnings)

Usage of deprecated APIs.

Affected:

  • datetime.utcnow()
  • Pydantic v1 APIs (parse_obj_as, from_orm)

Recommended Fix Priority

  1. Low effort, high value: deprecated (3) - easy fixes, good practice
  2. Medium effort: invalid-return-type (9) - add explicit returns
  3. Investigate: invalid-key (52) - may be ty bug with ASGI types
  4. Complex: invalid-type-form (51) - may need typing workarounds
  5. Wait for ty: call-non-callable, no-matching-overload - likely ty limitations

Configuration

Current suppressions in pyproject.toml:

[tool.ty.rules]
invalid-assignment = "ignore"
invalid-argument-type = "ignore"
invalid-type-form = "ignore"
unresolved-import = "ignore"
possibly-missing-attribute = "ignore"
no-matching-overload = "ignore"
invalid-return-type = "ignore"
invalid-base = "ignore"
non-subscriptable = "ignore"
deprecated = "ignore"
invalid-key = "ignore"
missing-argument = "ignore"
unresolved-attribute = "ignore"
call-non-callable = "ignore"
unsupported-operator = "ignore"
unsupported-base = "ignore"
unknown-argument = "ignore"
not-iterable = "ignore"
missing-typed-dict-key = "ignore"
invalid-method-override = "ignore"
conflicting-argument-forms = "ignore"
redundant-cast = "ignore"

Closes

Closes #4491

@JacobCoffee JacobCoffee requested review from a team as code owners November 26, 2025 06:12
@github-actions github-actions bot added area/ci This PR involves changes to the CI/Infra area/dependencies This PR involves changes to the dependencies size: small pr/internal labels Nov 26, 2025
- name: Execute Pre-Commit
run: pre-commit run --show-diff-on-failure --color=always --all-files

mypy:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be removed. See my comment in #4491

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I agree, mypy is still the most popular type-checker, while ty is not even in beta yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci This PR involves changes to the CI/Infra area/dependencies This PR involves changes to the dependencies pr/internal size: small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Swap to ty

4 participants