Skip to content

Checking call signatures of Type[C] objects #1831

Open
@JukkaL

Description

@JukkaL

Currently mypy doesn't complain about this code:

from typing import Type

class A:
    def __init__(self, x: int) -> None: pass

def f(t: Type[object]) -> None:
    t()  # ok, since `object()` is valid

f(A)  # no error reported!

This is caused by __init__ overrides not needing to be compatible with base classes.

It's not clear how to type check such code. Here are some ideas, some of which have been discussed before:

  • We could reject calling Type[C] and require Type[[ArgType, ...], C] for type objects that can be called. The argument types would specify a signature for __init__. This would require a PEP 484 (and a typing change). This has the problem of being backward incompatible. Additionally, it's not clear how to specify signatures with keyword arguments or optional arguments.
  • Similar to above, but by default Type[C] would take the __init__ signature from C, similar to how it behaves now. Unlike now, Type[D] would only be a subtype of Type[C] if the __init__ signature is compatible. Type[None, C] would be a type object that is not callable. Type[[X, ...], C] would also be supported and would support specifying a specific signature instead of just taking it from C.
  • Type[..., C] would be a callable type object which accepts arbitrary arguments.
  • Type[[T], C[T]] would perhaps also be valid for generic classes (T is a type variable).

Class methods also have this issue. We could support specifying the type of cls explicitly. For example:

class A:
    ...
    @classmethod
    def f(cls: Type[[int], A]) -> A:
        return cls(1)  # ok

(I known that this is an old issue, but I couldn't find a previous open issue.)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions