0

I'm trying to allow my class' __getitem__ override to return either a single float or a sequence of floats depending on whether a string or sequence of strings argument is provided respectively. To do this I am using the @overload decorator from the builtin typing module with two methods (and a third implementation method), however mypy is giving me the error "Overloaded function signatures 1 and 2 overlap with incompatible return types" on the line of my first overload. My only guess as to why this could be happening is that str is being treated as a Sequence[str], causing ambiguity.

class SimulationResults:
    ...

    # Mypy error occurs here
    @overload
    def __getitem__(self: Self, names: str) -> float:
        ...

    @overload
    def __getitem__(self: Self, names: Sequence[str]) -> Sequence[float]:
        ...

    def __getitem__(self: Self, names: str | Sequence[str]) -> float | Sequence[float]:
        def get_value(name: str) -> float:
            if name == self._time_var_name:
                return self._time[self._current_index]

            if name not in self._vars:
                raise KeyError(f"Variable '{name}' does not exist for this simulation")

            return self._vars[name][self._current_index]

        return (
            get_value(names)
            if isinstance(names, str)
            else tuple(get_value(name) for name in names)
        )

Could anyone clue me in on what's happening to cause this error, and if there are any ways to get around it? Thanks.

Owen Page
  • 33
  • 1
  • 7
  • 1
    See [this](https://stackoverflow.com/questions/60222982/type-annotation-for-overloads-that-exclude-types-something-vs-everything-else) in addition to the linked dupe. You're correct that `str` is a subtype of `Sequence[str]` and this is the issue cause. In short, your definition is correct until someone uses `value: Sequence[str] = 'foo'` and passes it to your `__getitem__`, causing incorrect inference. This is far from perfect, because some function can return `'foo'` with annotation `Sequence[str]` as well (e.g. just to shorten the code - it's correct, after all). – STerliakov Aug 18 '23 at 15:30
  • Does this answer your question? [mypy error, overload with Union/Optional, "Overloaded function signatures 1 and 2 overlap with incompatible return types"](https://stackoverflow.com/questions/53529693/mypy-error-overload-with-union-optional-overloaded-function-signatures-1-and) – STerliakov Aug 18 '23 at 15:30
  • Thanks @STerliakov, it's slightly less user-friendly, but I'll change the overload to accept `tuple[str, ...]` instead of `Sequence[str]` – Owen Page Aug 18 '23 at 15:43
  • 1
    Yeah, you can use `tuple[str, ...] | list[str] | set[str] | frozenset[str]` to support at least most common builtin structures. – STerliakov Aug 18 '23 at 16:35

0 Answers0