Skip to content

Should *args narrow in type guards? #14273

Open
@A5rocks

Description

@A5rocks

While making a PR I found a TODO that goes along the lines of "is *args support for TypeGuard even worth it?"

I want to approach this from a different perspective. Pyright supports this:

from typing_extensions import TypeGuard

def typeguard(*args: object) -> TypeGuard[int]:
  ...

def f(x: object, y: object) -> None:
  if typeguard(x, y):
    reveal_type(x)  # revealed `int`
    reveal_type(y)  # revealed `object`

I'm ... not quite sure that should be allowed. Going strictly by the specification:

Type checkers should assume that type narrowing should be applied to the expression that is passed as the first positional argument to a user-defined type guard.

(PEP 647, emphasis my own)

Notice how it says first and argument (no s). (and the "passed as" sets up that we're talking about function signature, not how the function is called)


Anyways, given that:

  • other type checkers support it
  • but it doesn't seem widely used (there's been no issue on here AFAICT about it)
  • it's not part of the specification
  • it's not clear how it should extend (first *args argument (like pyright)? all of them (which would allow more flexibility)?)

Should this even be attempted in the first place? I'm in favor of removing the TODO.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions