python / python/mypy

"error: 'type' expects no type arguments, but 1 given" if type is aliased to another name

Open
#10,068 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

affects-typeshed bug topic-pep-585 topic-type-alias
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

With the implementation of PEP 585 in Python 3.9, type now accepts a generic parameter. This makes typing.Type obsolete, reflected in its deprecation.

However, if the type built-in is assigned to another name and then used in a type declaration, mypy produces an error.

This does not occur with other types affected by PEP 585, or at least not all of them. I can confirm list and dict do not exhibit this behavior.

To Reproduce

Example code file:

generictype.py

Type = type

class MyInt(int):
    pass

x_type: Type[int] = MyInt
  1. Install mypy into a Python 3.9 environment.
  2. Execute mypy against the script: mypy .\generictype.py. No arguments or configuration are required.

Expected Behavior

This should result in a success run with no errors:

> mypy .\generictype.py
Success: no issues found in 1 source file

Actual Behavior

mypy identifies an error:

> mypy .\generictype.py
generictype.py:3: error: "type" expects no type arguments, but 1 given
Found 1 error in 1 file (checked 1 source file)

Also note that using x_type: type[int] = MyInt directly eliminates the error.

Your Environment

  • Mypy version used: mypy 0.800
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: Python 3.9.1 (inside a venv)
  • Operating system and version: Windows 10

Motivation

My actual code doesn't look exactly like the reproducing code above. I encountered it trying to make my code backwards compatible with Python 3.7+. My real usage looks more like this:

from __future__ import annotations

if sys.version_info >= (3, 9):
    List = list
    Type = type
else:
    # Legacy generic type annotation classes
    # Deprecated in Python 3.9
    # Remove once we no longer support Python 3.8 or lower
    from typing import List
    from typing import Type

class MyCustomContext:
    data: List[int]

    def __init__(self):
        self.data = []

    def __enter__(self) -> MyCustomContext:
        return self

    def add(i: int) -> None:
        self.data.append(i)

    def __exit__(
        self,
        ex_type: Optional[Type[Exception]],
        ex_value: Optional[Exception],
        ex_traceback: Optional[TracebackType],
    ) -> None:
        if ex_value is None and len(self.data) > 100:
            raise ValueError('Too much data')

For the time being, I can work around this by just continuing to use typing.Type, but I'd like to eliminate this deprecated class.

Contributor guide

Open the contributing guide

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 running the reported Python 3.9 reproducer in generictype.py with mypy and confirm the alias-specific error. Trace how mypy handles aliases of generic builtins, then add a regression test covering Type = type and verify that the check succeeds without breaking the existing list and dict behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.