Inferring parameter types and return type of a `type[T]`
Open
Nobody has claimed this yet.
feature
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
From this discussion at @microsoft/pyright:
@dataclass(kw_only = True) class User: id: int name: str class HasCls[**P, T](Protocol): cls: Callable[P, T] class Repository[T]: cls: type[T] def __init__(self, cls: type[T]) -> None: ... def create[**P](self: HasCls[P, T], *args: P.args, **kwargs: P.kwargs) -> T: ... class UserDatabase(Repository[User]): def __init__(self) -> None: ...Expected:
user = UserDatabase().create(id = 1, name = 'foo') # fine reveal_type(UserDatabase().create) # (*, id: int, name: str) -> User reveal_type(user) # User
# error: Invalid self argument "UserDatabase" to attribute function "create" with type "Callable[[HasCls[P, T], **P], T]" [misc]
user = UserDatabase().create(id = 1, name = 'foo')
reveal_type(UserDatabase().create) # (*args: Never, **kwargs: Never) -> User
reveal_type(user) # User
The pattern above is supported by Pyright, if not for a bug that this snippet helped discovering (which has since been fixed).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked minimal Python reproducer and compare mypy's strict-mode output with the expected reveal_type results for UserDatabase().create and user. The work is done when the type checker accepts the create call and infers the keyword-only constructor parameters and User return type without the invalid-self error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100