Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding type warning for lists of sortable elements

I've got a list of elements of a dataclass X (marked order=True) and pass them to max(). I get a type checking warning in my IDE: Expected type 'Iterable' (matched generic type 'Iterable[SupportsLessThanT]'), got 'List[X]' instead. How can I avoid this error? What do I have to declare to make the warning disappear? (I don't want to suppress it of course.)

I thought because the class X is marked as order=True it would be obviously sortable, so that passing it to max() should be no problem. But apparently this isn't known to the type system.

@dataclass(frozen=True, order=True)
class X:
    value: int

def f(xs: List[X]) -> None:
    q = max(xs)  # here's the above mentioned type checking warning

I tried inheriting various things in the class X but nothing helped.

Is there a supposed way to deal with this or do I have to ignore the warning?

like image 227
Alfe Avatar asked Aug 31 '25 18:08

Alfe


1 Answers

The code is fine as is. This is purely an issue of the type checker, in this case PyCharm/Intellij. Other type checkers such as MyPy correctly understand that the dataclass supports ordering.

# so.py
from typing import List
from dataclasses import dataclass


@dataclass(frozen=True, order=True)
class X:
    value: int

def f(xs: List[X]) -> None:
    q = max(xs)
python -m mypy so.py --strict
Success: no issues found in 1 source file

Since the builtin PyCharm/Intellij type checker is rarely up to date, it can be worthwhile not to treat it as authoritative. Rely on a second type checker and ignore the issue until the builtin type checker is updated.

If you want to help the builtin type checker, you can manually define a Protocol to express "this type is orderable". Inheriting the dataclass from this Protocol marks it as orderable.

from typing import List, Protocol
from dataclasses import dataclass

class Orderable(Protocol):
    def __lt__(self, other) -> bool:
        ...
    def __gt__(self, other) -> bool:
        ...
    # add more comparison methods as desired

@dataclass(frozen=True, order=True)
class X(Orderable):
    value: int

def f(xs: List[X]) -> None:
    q = max(xs)  # fine for PyCharm/Intellij
like image 91
MisterMiyagi Avatar answered Sep 02 '25 08:09

MisterMiyagi