Skip to content

Type narrowing on type[T] where T is a union alias of classes #3905

Description

@LoicRiegel

Summary

Hi! I hope this is not a duplicate:

main.py:

from typing import assert_never

class A: ...
class B: ...

type T = A | B

def f(t: type[T]) -> str:
    if issubclass(t, A):
        return "A"
    if issubclass(t, B):
        return "B"

    assert_never(t)

Ty reports this:

Type `@Todo & ~type[A] & ~type[B]` is not equivalent to `Never` (type-assertion-failure) [Ln 15, Col 5]
Inferred type of argument is `@Todo & ~type[A] & ~type[B]` [Ln 15, Col 18]
info: `Never` and `@Todo & ~type[A] & ~type[B]` are not equivalent types

ty.json:

{
    "environment": {
        "python-version": "3.12"
    },
    "rules": {
        "undefined-reveal": "ignore"
    }
}

Playground

I ran the same thing with mypy and looks like it's supported there.

Note that the equivalent code using an explicit union works with ty:

def f(t: type[A] | type[B]) -> str:
    if issubclass(t, A):
        return "A"
    if issubclass(t, B):
        return "B"

    assert_never(t)

Version

ty 0.0.56 (3078f9f 2026-07-01)

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions