Enum class rejected by a generic union
Author: kalekseevCreated Sep 18, 2026Updated Sep 18, 2026
Summary
ty 0.0.82 rejects this call. ty 0.0.81 and Pyright 1.1.410 accept it.
from collections.abc import Iterable
from enum import Enum
class Choice(Enum):
A = "a"
def accepts_choices[T](choices: Iterable[tuple[T, str]] | type[Enum]) -> None:
pass
accepts_choices(Choice)error[[invalid-argument-type](https://ty.dev/rules#invalid-argument-type)]: Argument to function `accepts_choices` is incorrect
--> a.py:18:17
|
18 | accepts_choices(Choice)
| ^^^^^^ Expected `Iterable[tuple[Unknown, str]]`, found `<class 'Choice'>`
info: type `<class 'Choice'>` is not assignable to protocol `Iterable[tuple[Unknown, str]]`
info: └── protocol member `__iter__` is incompatible
info: └── incompatible return types: `Iterator[Choice]` is not assignable to `Iterator[tuple[Unknown, str]]`
info: └── protocol `Iterator[Choice]` is not assignable to protocol `Iterator[tuple[Unknown, str]]`
info: └── protocol member `__next__` is incompatible
info: └── incompatible return types: `Choice` is not assignable to `tuple[Unknown, str]`
info: Function defined here
--> a.py:14:5
|
14 | def accepts_choices[T](choices: Iterable[tuple[T, str]] | type[Enum]) -> None:
| ^^^^^^^^^^^^^^^ --------------------------------------------- Parameter declared hereExpected: accept Choice through the type[Enum] union branch. That branch is absent from the diagnostic.
Replacing T with str, or using a legacy TypeVar with default=str, avoids the error.
This also affects Django field declarations with choices=SomeTextChoices or choices=SomeIntegerChoices.
Version
ty 0.0.82 (6999edb88 2026-09-17)
Source: astral-sh/ty