Skip to content

Accept more generic types as type[C] #15662

@eltoder

Description

@eltoder

Feature

It would be nice if the following worked:

from typing import Annotated, List, TypeVar

T = TypeVar("T")

def convert(val: object, ty: type[T]) -> T:
    raise NotImplementedError

reveal_type(convert([1], list[int]))
reveal_type(convert([1], List[int]))
reveal_type(convert(None, int | None))
reveal_type(convert(1, Annotated[int]))

Currently the first 2 calls type check as expected, but the following 2 calls fail with

type_t.py:10: note: Revealed type is "<nothing>"
type_t.py:10: error: Argument 2 to "convert" has incompatible type "UnionType"; expected "type[<nothing>]"  [arg-type]
type_t.py:11: note: Revealed type is "<nothing>"
type_t.py:11: error: Argument 2 to "convert" has incompatible type "object"; expected "type[<nothing>]"  [arg-type]

Technically int | None is not a type object, but neither are List[int] and list[int]. However, they are type specifications recognized by type checkers, and it is clear what the meaning of the call is.

Another option is to provide a new type like TypeSpec[T] to use for cases where the value is not necessarily a type object but is a valid type specification, if extending type is deemed not appropriate. The difference may be too subtle, though, and type already accepts some values which are not types per the example above.

If this works, type checkers can remove special cases for typing.cast function. It can be annotated simply as

def cast(typ: type[_T], val: Any) -> _T: ...

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions