Vulwsztyn
Vulwsztyn

Reputation: 2271

assert_type with callable

pyright seems to expect a name of the parameter in a Callable when using assert_type

For such code:

from typing import assert_type
from collections.abc import Callable
def tuple_of_nums(n: int) -> tuple[int,...]:
    return tuple(range(n))
assert_type(tuple_of_nums, Callable[[int], tuple[int,...]])

running pyright file.py yields:

file.py:5:13 - error: "assert_type" mismatch: expected "(int) -> tuple[int, ...]" but received "(n: int) -> tuple[int, ...]" (reportAssertTypeFailure)

The only difference being n: in the received function.

How do I make this type assertion work?

Upvotes: 1

Views: 58

Answers (1)

InSync
InSync

Reputation: 10673

There are two reasons for this.

First, the asserted signature (int) -> tuple[int, ...] only allows the lone argument to be passed in positionally, but the actual signature (n: int) -> tuple[int, ...] allows it to be passed as n as well, which causes a difference in arity.

Second, assert_type()'s semantics are not standardized. Here's everything what the specs have to say about it, save for an example (emphasis mine):

The function typing.assert_type(val, typ) allows users to ask a static type checker to confirm that val has an inferred type of typ.

When a type checker encounters a call to assert_type(), it should emit an error if the value is not of the specified type[.]

Neither the exact algorithm assert_type() should follow nor type inference is standardized, and so different type checkers might handle assert_type() differently.

In this case, the type checker is Pyright, and it checks for equivalency (or, more precisely, gradual equivalency) rather than assignability.

Upvotes: 2

Related Questions