python / python/typing

How to alias `Annotated` to a subscriptable type

Open
#779 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

topic: feature
Dominant language
Python
Stars
1.8k
Forks
302
Avg merge
23h
Merged PRs (30d)
8

Description

Hi, I want to create a type alias that simply wraps a tuple into Annotated.

PEP 593

I want to be able to write

SpecialReturn[int, bool, str]

And get

Annotated[Tuple[int, bool, str], 'special return!']

Among other things, I've tried:

class SpecialReturn():
    def __class_getitem__(self, params: Tuple[Any, ...]) -> Tuple[Any, ...]:
        return typing.cast(
            Tuple[Any, ...],
            _typing.Annotated[
                typing.Tuple.__getitem__(params),
                'multiple_return',
            ]
        )

Which mypy is happy with the declaration, but not using it:

import typing

from typing import Annotated, Any, Tuple


class SpecialReturn():
    def __class_getitem__(self, params: Tuple[Any, ...]) -> Tuple[Any, ...]:
        return typing.cast(
            Tuple[Any, ...],
            Annotated[
                typing.Tuple.__getitem__(params),
                'multiple_return',
            ]
        )


def test() -> SpecialReturn[int, int]:
    return 1, 2
test8.py:17: error: "SpecialReturn" expects no type arguments, but 2 given
test8.py:18: error: Incompatible return value type (got "Tuple[int, int]", expected "SpecialReturn")

Which happens because I guess mypy does not evaluate the type annotation, it just treats SpecialReturn as a separate type. I am not sure what is the reasoning behind this, but I assume there it makes sense in some way(?).

So, is there any alternative? How do achieve this? I essentially want to alias Tuple and be able to find out at runtime if the type is a normal tuple or my special one.

My first jab at this, and what I think makes most sense to a Python developer is the following

from typing import Tuple


class SpecialReturn(Tuple):
    pass


def test() -> SpecialReturn[int, int]:
    return 1, 2

But mypy can't handle it either:

test.py:4: error: Missing type parameters for generic type "Tuple"
test.py:8: error: "SpecialReturn" expects no type arguments, but 2 given
test.py:9: error: Incompatible return value type (got "Tuple[int, int]", expected "SpecialReturn")

I was thinking maybe something like this was possible with Annotated, but it seems not.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading PEP 593 and the examples in this issue, then review how the typing project represents Annotated, generic aliases, and class_getitem. The issue does not name a file, test, or implementation entry point, and completion would require settling whether this behavior should be supported and how it should be specified.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.