Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expected class type but received "type" #2058

Closed
Timmmm opened this issue Jul 5, 2021 · 5 comments
Closed

Expected class type but received "type" #2058

Timmmm opened this issue Jul 5, 2021 · 5 comments
Labels
as designed Not a bug, working as intended

Comments

@Timmmm
Copy link

Timmmm commented Jul 5, 2021

The following code gives a type error:

from __future__ import annotations # I'm using Python 3.8
from typing import Tuple

def foo(x: Tuple[type, ...]):
    return type("foo", x, {})

It gives this error for x:

    return type("foo", x, {})
                       ^
Expected class type but received "type"
(parameter) x: Tuple[type, ...]

Even though the type of x looks like it matches the type constructor:

    @overload
    def __init__(self, name: str, bases: Tuple[type, ...], dict: Dict[str, Any], **kwds: Any) -> None: ...

VS Code extension or command-line
Via Pylance 2021.6.3

Additional context
On Mac, with Python 3.8

@erictraut
Copy link
Collaborator

A static type checker needs to understand the class hierarchy for classes. It looks like you're dynamically creating new classes here. This is the equivalent of:

def foo(x: Tuple[type, ...]):
    class DynamicClass(x):
        ...

    return DynamicClass

Pyright also emits an error in this case.

If you want to use static analysis, you should avoid this sort of dynamic class construction.

You can suppress the error using a # type: ignore.

@erictraut erictraut added the as designed Not a bug, working as intended label Jul 5, 2021
@Timmmm
Copy link
Author

Timmmm commented Jul 5, 2021

Oooh I see. The error message could be improved a bit. If I'm understanding you correctly it should say something more like:

Expected static class type but received runtime "type"

Maybe. Anyway I'll close this. Thanks for the help (again)!

@Timmmm Timmmm closed this as completed Jul 5, 2021
@davidism
Copy link

This makes it impossible to type check Flask-SQLAlchemy's db.Model base class. All of a project's model classes will now show this error if I enable type annotations in Flask-SQLAlchemy.

@Timmmm
Copy link
Author

Timmmm commented Sep 13, 2022

There's just lots of Python out there that can't really be statically type checked because it wasn't written in a way that's amenable to static type checking.

Python type hinting is relatively new and there are a lot of issues with it so I imagine it will take a long time to get to the point where you can expect most code to be statically typed like you can with JavaScript/Typescript.

You just have to resort to Any, instanceof, cast and so on.

@erictraut
Copy link
Collaborator

@davidism, I saw your related post in the mypy issue tracker.

First of all, thank you for adding annotations to the Flask-SQLAlchemy library. It's great to hear that effort is underway!

The code snippet that you posted in the mypy issue type checks in pyright without generating a type errors, although pyright does need to make a somewhat fragile assumption here. Namely, it assumes that a value that is annotated with the type Type[object] should be treated the same as object if it is used in a base class list within a class definition. This is fragile because any subclass of Type[object] (which could be any class) might be used at runtime, and the type checker has no knowledge of what attributes or methods that base class contributes. So I'm sympathetic to the fact that mypy emits an error in this situation.

If you'd like to discuss this further or explore solutions to other issues you're encountering as you add annotations, I recommend starting a new thread in the pyright discussions forum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
as designed Not a bug, working as intended
Projects
None yet
Development

No branches or pull requests

3 participants