[ty] Support isinstance() and issubclass() narrowing when the second argument is a typing.py stdlib alias (#21391)

## Summary

A followup to https://github.com/astral-sh/ruff/pull/21386

## Test Plan

New mdtests added
This commit is contained in:
Alex Waygood 2025-11-11 21:09:24 +00:00 committed by GitHub
parent 4373974dd9
commit 43297d3455
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 89 additions and 4 deletions

View file

@ -147,6 +147,25 @@ def _(x: int | str | bytes):
reveal_type(x) # revealed: (int & Unknown) | (str & Unknown) | (bytes & Unknown)
```
## `classinfo` is a `typing.py` special form
Certain special forms in `typing.py` are aliases to classes elsewhere in the standard library; these
can be used in `isinstance()` and `issubclass()` checks. We support narrowing using them:
```py
import typing as t
def f(x: dict[str, int] | list[str], y: object):
if isinstance(x, t.Dict):
reveal_type(x) # revealed: dict[str, int]
else:
reveal_type(x) # revealed: list[str]
if isinstance(y, t.Callable):
# TODO: a better top-materialization for `Callable`s (https://github.com/astral-sh/ty/issues/1426)
reveal_type(y) # revealed: () -> object
```
## Class types
```py