-- Test cases for the type checker related to varargs. -- Varargs within body -- ------------------- [case testVarArgsWithinFunction] from typing import Tuple def f( *b: 'B') -> None: ab: Tuple[B, ...] ac: Tuple[C, ...] if int(): b = ac # E: Incompatible types in assignment (expression has type "tuple[C, ...]", variable has type "tuple[B, ...]") ac = b # E: Incompatible types in assignment (expression has type "tuple[B, ...]", variable has type "tuple[C, ...]") b = ab ab = b class B: pass class C: pass [builtins fixtures/tuple.pyi] [out] [case testVarArgsAreTuple] from typing import Tuple, Sequence def want_tuple(types: Tuple[type, ...]): pass def want_sequence(types: Sequence[type]): pass def test(*t: type) -> None: want_tuple(t) want_sequence(t) [builtins fixtures/tuple.pyi] [out] -- Calling varargs function -- ------------------------ [case testCallingVarArgsFunction] def f( *a: 'A') -> None: pass def g() -> None: pass class A: pass class B(A): pass class C: pass a: A b: B c: C f(c) # E: Argument 1 to "f" has incompatible type "C"; expected "A" f(a, b, c) # E: Argument 3 to "f" has incompatible type "C"; expected "A" f(g()) # E: "g" does not return a value (it only ever returns None) \ # E: Argument 1 to "f" has incompatible type "None"; expected "A" f(a, g()) # E: "g" does not return a value (it only ever returns None) \ # E: Argument 2 to "f" has incompatible type "None"; expected "A" f() f(a) f(b) f(a, b, a, b) [builtins fixtures/list.pyi] [case testCallingVarArgsFunctionWithAlsoNormalArgs] def f(a: 'C', *b: 'A') -> None: pass class A: pass class B(A): pass class C: pass a: A b: B c: C f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "C" f(c, c) # E: Argument 2 to "f" has incompatible type "C"; expected "A" f(c, a, b, c) # E: Argument 4 to "f" has incompatible type "C"; expected "A" f(c) f(c, a) f(c, b, b, a, b) [builtins fixtures/list.pyi] [case testCallingVarArgsFunctionWithDefaultArgs] # flags: --implicit-optional --no-strict-optional def f(a: 'C' = None, *b: 'A') -> None: pass class A: pass class B(A): pass class C: pass a: A b: B c: C f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "C | None" f(c, c) # E: Argument 2 to "f" has incompatible type "C"; expected "A" f(c, a, b, c) # E: Argument 4 to "f" has incompatible type "C"; expected "A" f() f(c) f(c, a) f(c, b, b, a, b) [builtins fixtures/list.pyi] [case testCallVarargsFunctionWithIterable] from typing import Iterable it1: Iterable[int] it2: Iterable[str] def f(*x: int) -> None: pass f(*it1) f(*it2) # E: Argument 1 to "f" has incompatible type "*Iterable[str]"; expected "int" [builtins fixtures/for.pyi] [case testCallVarargsFunctionWithTwoTupleStarArgs] from typing import TypeVar, Tuple T1 = TypeVar('T1') T2 = TypeVar('T2') T3 = TypeVar('T3') T4 = TypeVar('T4') def f(a: T1, b: T2, c: T3, d: T4) -> Tuple[T1, T2, T3, T4]: ... x: Tuple[int, str] y: Tuple[float, bool] reveal_type(f(*x, *y)) # N: Revealed type is "tuple[builtins.int, builtins.str, builtins.float, builtins.bool]" [builtins fixtures/list.pyi] [case testCallVarargsFunctionWithIterableAndPositional] from typing import Iterable it1: Iterable[int] def f(*x: int) -> None: pass f(*it1, 1, 2) f(*it1, 1, *it1, 2) f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" [builtins fixtures/for.pyi] [case testCallVarargsFunctionWithTupleAndPositional] def f(*x: int) -> None: pass it1 = (1, 2) it2 = ('',) f(*it1, 1, 2) f(*it1, 1, *it1, 2) f(*it1, 1, *it2, 2) # E: Argument 3 to "f" has incompatible type "*tuple[str]"; expected "int" f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" [builtins fixtures/for.pyi] [case testCallVarArgsWithMatchingNamedArgument] def foo(*args: int) -> None: ... foo(args=1) # E: Unexpected keyword argument "args" for "foo" def bar(*args: int, **kwargs: str) -> None: ... bar(args=1) # E: Argument "args" to "bar" has incompatible type "int"; expected "str" [builtins fixtures/for.pyi] -- Calling varargs function + type inference -- ----------------------------------------- [case testTypeInferenceWithCalleeVarArgs] from typing import TypeVar T = TypeVar('T') def f( *a: T) -> T: pass class A: pass class B(A): pass class C: pass a: A b: B c: C o: object if int(): a = f(o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") if int(): b = f(b, a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): b = f(a, b) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): o = f() if int(): a = f(a) if int(): a = f(b) if int(): a = f(a, b, a) if int(): o = f(a, b, o) if int(): c = f(c) [builtins fixtures/list.pyi] [case testTypeInferenceWithCalleeVarArgsAndDefaultArgs] # flags: --no-strict-optional from typing import TypeVar T = TypeVar('T') a = None # type: A o = None # type: object def f(a: T, b: T = None, *c: T) -> T: pass class A: pass if int(): a = f(o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") if int(): a = f(a, o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") if int(): a = f(a, a, o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") if int(): a = f(a, a, a, o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") if int(): a = f(a) if int(): a = f(a, a) if int(): a = f(a, a, a) [builtins fixtures/list.pyi] -- Calling normal function with varargs -- ------------------------------------ [case testCallingWithListVarArgs] from typing import List, Any, cast def f(a: 'A', b: 'B') -> None: pass class A: pass class B: pass aa: List[A] ab: List[B] a: A b: B f(*aa) # E: Argument 1 to "f" has incompatible type "*list[A]"; expected "B" f(a, *ab) # Ok f(a, b) (cast(Any, f))(*aa) # IDEA: Move to check-dynamic? (cast(Any, f))(a, *ab) # IDEA: Move to check-dynamic? [builtins fixtures/list.pyi] [case testCallingWithTupleVarArgs] def f(a: 'A', b: 'B', c: 'C') -> None: pass class A: pass class B: pass class C: pass class CC(C): pass a: A b: B c: C cc: CC f(*(a, b, b)) # E: Argument 1 to "f" has incompatible type "*tuple[A, B, B]"; expected "C" f(*(b, b, c)) # E: Argument 1 to "f" has incompatible type "*tuple[B, B, C]"; expected "A" f(a, *(b, b)) # E: Argument 2 to "f" has incompatible type "*tuple[B, B]"; expected "C" f(b, *(b, c)) # E: Argument 1 to "f" has incompatible type "B"; expected "A" f(*(a, b)) # E: Missing positional arguments "b", "c" in call to "f" f(*(a, b, c, c)) # E: Too many arguments for "f" f(a, *(b, c, c)) # E: Too many arguments for "f" f(*(a, b, c)) f(a, *(b, c)) f(a, b, *(c,)) f(a, *(b, cc)) [builtins fixtures/tuple.pyi] [case testInvalidVarArg] from typing import Any def f(a: 'A') -> None: pass class A: pass a = A() f(*None) # E: Expected iterable as variadic argument f(*a) # E: Expected iterable as variadic argument f(*(a,)) f(*4) # E: Expected iterable as variadic argument f(a, *4) # E: Expected iterable as variadic argument def main(f: Any) -> None: f(*3) # E: Expected iterable as variadic argument [builtins fixtures/tuple.pyi] -- Calling varargs function with varargs -- ------------------------------------- [case testCallingVarArgsFunctionWithListVarArgs] from typing import List def f(a: 'A', *b: 'B') -> None: pass def g(a: 'A', *b: 'A') -> None: pass class A: pass class B: pass aa: List[A] ab: List[B] a: A b: B f(*aa) # E: Argument 1 to "f" has incompatible type "*list[A]"; expected "B" f(a, *aa) # E: Argument 2 to "f" has incompatible type "*list[A]"; expected "B" f(b, *ab) # E: Argument 1 to "f" has incompatible type "B"; expected "A" f(a, a, *ab) # E: Argument 2 to "f" has incompatible type "A"; expected "B" f(a, b, *aa) # E: Argument 3 to "f" has incompatible type "*list[A]"; expected "B" f(b, b, *ab) # E: Argument 1 to "f" has incompatible type "B"; expected "A" g(*ab) # E: Argument 1 to "g" has incompatible type "*list[B]"; expected "A" f(a, *ab) f(a, b, *ab) f(a, b, b, *ab) g(*aa) [builtins fixtures/list.pyi] [case testCallingVarArgsFunctionWithTupleVarArgs] def f(a: 'A', *b: 'B') -> None: pass class A: pass class B: pass class C: pass class CC(C): pass a: A b: B c: C cc: CC f(*(b, b, b)) # E: Argument 1 to "f" has incompatible type "*tuple[B, B, B]"; expected "A" f(*(a, a, b)) # E: Argument 1 to "f" has incompatible type "*tuple[A, A, B]"; expected "B" f(*(a, b, a)) # E: Argument 1 to "f" has incompatible type "*tuple[A, B, A]"; expected "B" f(a, *(a, b)) # E: Argument 2 to "f" has incompatible type "*tuple[A, B]"; expected "B" f(b, *(b, b)) # E: Argument 1 to "f" has incompatible type "B"; expected "A" f(b, b, *(b,)) # E: Argument 1 to "f" has incompatible type "B"; expected "A" f(a, a, *(b,)) # E: Argument 2 to "f" has incompatible type "A"; expected "B" f(a, b, *(a,)) # E: Argument 3 to "f" has incompatible type "*tuple[A]"; expected "B" f(*()) # E: Too few arguments for "f" f(*(a, b, b)) f(a, *(b, b)) f(a, b, *(b,)) [builtins fixtures/list.pyi] -- Varargs special cases -- --------------------- [case testDynamicVarArg] from typing import Any def f(a: 'A') -> None: pass def g(a: 'A', *b: 'A') -> None: pass class A: pass d: Any a: A f(a, a, *d) # E: Too many arguments for "f" f(a, *d) # Ok f(*d) # Ok g(*d) g(a, *d) g(a, a, *d) [builtins fixtures/list.pyi] [case testListVarArgsAndSubtyping] from typing import List def f( *a: 'A') -> None: pass def g( *a: 'B') -> None: pass class A: pass class B(A): pass aa: List[A] ab: List[B] g(*aa) # E: Argument 1 to "g" has incompatible type "*list[A]"; expected "B" f(*aa) f(*ab) g(*ab) [builtins fixtures/list.pyi] [case testCallerVarArgsAndDefaultArgs] # flags: --implicit-optional --no-strict-optional def f(a: 'A', b: 'B' = None, *c: 'B') -> None: pass class A: pass class B: pass a, b = None, None # type: (A, B) f(*()) # E: Too few arguments for "f" f(a, *[a]) # E: Argument 2 to "f" has incompatible type "*list[A]"; expected "B | None" \ # E: Argument 2 to "f" has incompatible type "*list[A]"; expected "B" f(a, b, *[a]) # E: Argument 3 to "f" has incompatible type "*list[A]"; expected "B" f(*(a, a, b)) # E: Argument 1 to "f" has incompatible type "*tuple[A, A, B]"; expected "B | None" f(*(a,)) f(*(a, b)) f(*(a, b, b, b)) f(a, *[]) f(a, *[b]) f(a, *[b, b]) [builtins fixtures/list.pyi] [case testVarArgsAfterKeywordArgInCall1] # see: mypy issue #2729 def f(x: int, y: str) -> None: pass f(x=1, *[2]) [builtins fixtures/list.pyi] [out] main:3: error: "f" gets multiple values for keyword argument "x" main:3: error: Argument 1 to "f" has incompatible type "*list[int]"; expected "str" [case testVarArgsAfterKeywordArgInCall2] # see: mypy issue #2729 def f(x: int, y: str) -> None: pass f(y='x', *[1]) [builtins fixtures/list.pyi] [out] main:3: error: "f" gets multiple values for keyword argument "y" main:3: error: Argument 1 to "f" has incompatible type "*list[int]"; expected "str" [case testVarArgsAfterKeywordArgInCall3] def f(x: int, y: str) -> None: pass f(y='x', *(1,)) [builtins fixtures/list.pyi] [case testVarArgsAfterKeywordArgInCall4] def f(x: int, *, y: str) -> None: pass f(y='x', *[1]) [builtins fixtures/list.pyi] [case testVarArgsAfterKeywordArgInCall5] def f(x: int, *, y: str) -> None: pass f(y='x', *(1,)) [builtins fixtures/list.pyi] [case testVarArgsEmptyList] from typing import List def foo() -> None: pass lst: List[int] = [] foo(*lst) [builtins fixtures/list.pyi] [case testVarArgsEmptyTuple] def foo() -> None: pass foo(*()) [builtins fixtures/tuple.pyi] -- Overloads + varargs -- ------------------- [case testIntersectionTypesAndVarArgs] # flags: --no-strict-optional from foo import * [file foo.pyi] from typing import overload a, b = None, None # type: (A, B) if int(): b = f() # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): b = f(a, b) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): a = f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A") if int(): a = f(b, b) # E: Incompatible types in assignment (expression has type "B", variable has type "A") if int(): b = f(a, *[b]) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): b = f(*()) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): b = f(*(a,)) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): b = f(*(a, b)) # E: Incompatible types in assignment (expression has type "A", variable has type "B") if int(): a = f(*(b,)) # E: Incompatible types in assignment (expression has type "B", variable has type "A") if int(): a = f(*(b, b)) # E: Incompatible types in assignment (expression has type "B", variable has type "A") if int(): a = f(*[b]) # E: Incompatible types in assignment (expression has type "B", variable has type "A") a = f() a = f(a) a = f(a, b) b = f(b) b = f(b, b) a = f(a, *[b]) a = f(*()) a = f(*(a,)) a = f(*(a, b)) b = f(*(b,)) b = f(*(b, b)) b = f(*[b]) class A: pass class B: pass @overload def f(a: A = None, *b: B) -> A: pass @overload def f(a: B, *b: B) -> B: pass [builtins fixtures/list.pyi] -- Caller varargs + type inference -- ------------------------------- [case testCallerVarArgsListWithTypeInference] from typing import List, TypeVar, Tuple S = TypeVar('S') T = TypeVar('T') def f(a: S, *b: T) -> Tuple[S, T]: pass class A: pass class B: pass a: A b: B aa: List[A] if int(): a, b = f(*aa) # E: Argument 1 to "f" has incompatible type "*list[A]"; expected "B" if int(): b, b = f(*aa) # E: Argument 1 to "f" has incompatible type "*list[A]"; expected "B" if int(): a, a = f(b, *aa) # E: Argument 1 to "f" has incompatible type "B"; expected "A" if int(): b, b = f(b, *aa) # E: Argument 2 to "f" has incompatible type "*list[A]"; expected "B" if int(): b, b = f(b, b, *aa) # E: Argument 3 to "f" has incompatible type "*list[A]"; expected "B" if int(): a, b = f(a, *a) # E: Expected iterable as variadic argument if int(): a, b = f(*a) # E: Expected iterable as variadic argument if int(): a, a = f(*aa) if int(): b, a = f(b, *aa) if int(): b, a = f(b, a, *aa) [builtins fixtures/list.pyi] [case testCallerVarArgsTupleWithTypeInference] from typing import TypeVar, Tuple S = TypeVar('S') T = TypeVar('T') def f(a: S, b: T) -> Tuple[S, T]: pass class A: pass class B: pass a: A b: B if int(): a, a = f(*(a, b)) # E: Argument 1 to "f" has incompatible type "*tuple[A, B]"; expected "A" if int(): b, b = f(a, *(b,)) # E: Argument 1 to "f" has incompatible type "A"; expected "B" if int(): a, a = f(*(a, b)) # E: Argument 1 to "f" has incompatible type "*tuple[A, B]"; expected "A" if int(): b, b = f(a, *(b,)) # E: Argument 1 to "f" has incompatible type "A"; expected "B" if int(): a, b = f(*(a, b, b)) # E: Too many arguments for "f" if int(): a, b = f(*(a, b)) if int(): a, b = f(a, *(b,)) [builtins fixtures/list.pyi] [case testCallerVarargsAndComplexTypeInference] from typing import List, TypeVar, Generic, Tuple T = TypeVar('T') S = TypeVar('S') a: A b: B ao: List[object] aa: List[A] ab: List[B] class G(Generic[T]): def f(self, *a: S) -> Tuple[List[S], List[T]]: pass class A: pass class B: pass if int(): a, aa = G().f(*[a]) # E: Incompatible types in assignment (expression has type "list[A]", variable has type "A") if int(): aa, a = G().f(*[a]) # E: Incompatible types in assignment (expression has type "list[Never]", variable has type "A") if int(): ab, aa = G().f(*[a]) # E: Argument 1 to "f" of "G" has incompatible type "*list[A]"; expected "B" if int(): ao, ao = G().f(*[a]) if int(): aa, aa = G().f(*[a]) [builtins fixtures/list.pyi] [case testCallerTupleVarArgsAndGenericCalleeVarArg] from typing import TypeVar T = TypeVar('T') def f(*args: T) -> T: ... reveal_type(f(*(1, None))) # N: Revealed type is "Literal[1]? | None" reveal_type(f(1, *(None, 1))) # N: Revealed type is "Literal[1]? | None" reveal_type(f(1, *(1, None))) # N: Revealed type is "Literal[1]? | None" [builtins fixtures/tuple.pyi] -- Comment signatures -- ------------------ [case testVarArgsAndCommentSignature] import typing def f(*x): # type: (*int) -> None pass f(1) f(1, 2) f('') # E: Argument 1 to "f" has incompatible type "str"; expected "int" f(1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" [builtins fixtures/list.pyi] -- Subtyping -- --------- [case testVarArgsFunctionSubtyping] from typing import Callable x: Callable[[int], None] def f(*x: int) -> None: pass def g(*x: str) -> None: pass x = f x = g # E: Incompatible types in assignment (expression has type "def g(*x: str) -> None", variable has type "Callable[[int], None]") [builtins fixtures/list.pyi] [out] -- Decorated method where self is implied by *args -- ----------------------------------------------- [case testVarArgsCallableSelf] from typing import Callable def cm(func) -> Callable[..., None]: pass class C: @cm def foo(self) -> None: pass C().foo() C().foo(1) # The decorator's return type says this should be okay [case testInvariantDictArgNote] from typing import Dict, Sequence def f(x: Dict[str, Sequence[int]]) -> None: pass def g(x: Dict[str, float]) -> None: pass def h(x: Dict[str, int]) -> None: pass a = {'a': [1, 2]} b = {'b': ['c', 'd']} c = {'c': 1.0} d = {'d': 1} f(a) # E: Argument 1 to "f" has incompatible type "dict[str, list[int]]"; expected "dict[str, Sequence[int]]" \ # N: "dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance \ # N: Consider using "Mapping" instead, which is covariant in the value type f(b) # E: Argument 1 to "f" has incompatible type "dict[str, list[str]]"; expected "dict[str, Sequence[int]]" g(c) g(d) # E: Argument 1 to "g" has incompatible type "dict[str, int]"; expected "dict[str, float]" \ # N: "dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance \ # N: Consider using "Mapping" instead, which is covariant in the value type h(c) # E: Argument 1 to "h" has incompatible type "dict[str, float]"; expected "dict[str, int]" h(d) [builtins fixtures/dict.pyi] [typing fixtures/typing-medium.pyi] [case testInvariantListArgNote] from typing import List, Union def f(numbers: List[Union[int, float]]) -> None: pass a = [1, 2] f(a) # E: Argument 1 to "f" has incompatible type "list[int]"; expected "list[int | float]" \ # N: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance \ # N: Consider using "Sequence" instead, which is covariant x = [1] y = ['a'] if int(): x = y # E: Incompatible types in assignment (expression has type "list[str]", variable has type "list[int]") [builtins fixtures/list.pyi] [case testInvariantTypeConfusingNames] from typing import TypeVar class Listener: pass class DictReader: pass def f(x: Listener) -> None: pass def g(y: DictReader) -> None: pass a = [1, 2] b = {'b': 1} f(a) # E: Argument 1 to "f" has incompatible type "list[int]"; expected "Listener" g(b) # E: Argument 1 to "g" has incompatible type "dict[str, int]"; expected "DictReader" [builtins fixtures/dict.pyi] [case testInvariantTypeConfusingNames2] from typing import Iterable, Generic, TypeVar, List T = TypeVar('T') class I(Iterable[T]): ... class Bad(Generic[T]): ... def bar(*args: float) -> float: ... good1: Iterable[float] good2: List[float] good3: I[float] bad1: I[str] bad2: Bad[float] bar(*good1) bar(*good2) bar(*good3) bar(*bad1) # E: Argument 1 to "bar" has incompatible type "*I[str]"; expected "float" bar(*bad2) # E: Expected iterable as variadic argument [builtins fixtures/dict.pyi] -- Keyword arguments unpacking [case testUnpackKwargsReveal] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int def foo(arg: bool, **kwargs: Unpack[Person]) -> None: ... reveal_type(foo) # N: Revealed type is "def (arg: builtins.bool, **kwargs: Unpack[TypedDict('__main__.Person', {'name': builtins.str, 'age': builtins.int})])" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackOutsideOfKwargs] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int def foo(x: Unpack[Person]) -> None: # E: Unpack is only valid in a variadic position ... def bar(x: int, *args: Unpack[Person]) -> None: # E: "Person" cannot be unpacked (must be tuple or TypeVarTuple) ... def baz(**kwargs: Unpack[Person]) -> None: # OK ... [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackWithoutTypedDict] from typing_extensions import Unpack def foo(**kwargs: Unpack[dict]) -> None: # E: Unpack item in ** parameter must be a TypedDict ... [builtins fixtures/dict.pyi] [case testUnpackWithDuplicateKeywords] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int def foo(name: str, **kwargs: Unpack[Person]) -> None: # E: Overlap between parameter names and ** TypedDict items: "name" ... [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackWithDuplicateKeywordKwargs] from typing_extensions import Unpack from typing import Dict, List, TypedDict class Spec(TypedDict): args: List[int] kwargs: Dict[int, int] def foo(**kwargs: Unpack[Spec]) -> None: # Allowed ... foo(args=[1], kwargs={"2": 3}) # E: Dict entry 0 has incompatible type "str": "int"; expected "int": "int" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsNonIdentifier] from typing import TypedDict from typing_extensions import Unpack Weird = TypedDict("Weird", {"@": int}) def foo(**kwargs: Unpack[Weird]) -> None: reveal_type(kwargs["@"]) # N: Revealed type is "builtins.int" foo(**{"@": 42}) foo(**{"no": "way"}) # E: Argument 1 to "foo" has incompatible type "**dict[str, str]"; expected "int" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsEmpty] from typing import TypedDict from typing_extensions import Unpack Empty = TypedDict("Empty", {}) def foo(**kwargs: Unpack[Empty]) -> None: reveal_type(kwargs) # N: Revealed type is "TypedDict('__main__.Empty', {})" foo() foo(x=1) # E: Unexpected keyword argument "x" for "foo" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackTypedDictTotality] from typing import TypedDict from typing_extensions import Unpack class Circle(TypedDict, total=True): radius: int color: str x: int y: int def foo(**kwargs: Unpack[Circle]): ... foo(x=0, y=0, color='orange') # E: Missing named argument "radius" for "foo" class Square(TypedDict, total=False): side: int color: str def bar(**kwargs: Unpack[Square]): ... bar(side=12) [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackUnexpectedKeyword] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict, total=False): name: str age: int def foo(**kwargs: Unpack[Person]) -> None: ... foo(name='John', age=42, department='Sales') # E: Unexpected keyword argument "department" for "foo" foo(name='Jennifer', age=38) [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKeywordTypes] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int def foo(**kwargs: Unpack[Person]): ... foo(name='John', age='42') # E: Argument "age" to "foo" has incompatible type "str"; expected "int" foo(name='Jennifer', age=38) [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKeywordTypesTypedDict] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int class LegacyPerson(TypedDict): name: str age: str def foo(**kwargs: Unpack[Person]) -> None: ... lp = LegacyPerson(name="test", age="42") foo(**lp) # E: Argument "age" to "foo" has incompatible type "str"; expected "int" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testFunctionBodyWithUnpackedKwargs] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int def foo(**kwargs: Unpack[Person]) -> int: name: str = kwargs['name'] age: str = kwargs['age'] # E: Incompatible types in assignment (expression has type "int", variable has type "str") department: str = kwargs['department'] # E: TypedDict "Person" has no key "department" return kwargs['age'] [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsOverrides] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int class Base: def foo(self, **kwargs: Unpack[Person]) -> None: ... class SubGood(Base): def foo(self, *, name: str, age: int, extra: bool = False) -> None: ... class SubBad(Base): def foo(self, *, name: str, age: str) -> None: ... # E: Argument 2 of "foo" is incompatible with supertype "Base"; supertype defines the argument type as "int" \ # N: This violates the Liskov substitution principle \ # N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsOverridesTypedDict] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int class PersonExtra(Person, total=False): extra: bool class Unrelated(TypedDict): baz: int class Base: def foo(self, **kwargs: Unpack[Person]) -> None: ... class SubGood(Base): def foo(self, **kwargs: Unpack[PersonExtra]) -> None: ... class SubBad(Base): def foo(self, **kwargs: Unpack[Unrelated]) -> None: ... # E: Signature of "foo" incompatible with supertype "Base" \ # N: Superclass: \ # N: def foo(*, name: str, age: int) -> None \ # N: Subclass: \ # N: def foo(self, *, baz: int) -> None [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsGeneric] from typing import Generic, TypedDict, TypeVar from typing_extensions import Unpack T = TypeVar("T") class Person(TypedDict, Generic[T]): name: str value: T def foo(**kwargs: Unpack[Person[T]]) -> T: ... reveal_type(foo(name="test", value=42)) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsInference] from typing import Generic, TypedDict, TypeVar, Protocol from typing_extensions import Unpack T_contra = TypeVar("T_contra", contravariant=True) class CBPerson(Protocol[T_contra]): def __call__(self, **kwargs: Unpack[Person[T_contra]]) -> None: ... T = TypeVar("T") class Person(TypedDict, Generic[T]): name: str value: T def test(cb: CBPerson[T]) -> T: ... def foo(*, name: str, value: int) -> None: ... reveal_type(test(foo)) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsOverload] from typing import TypedDict, Any, overload from typing_extensions import Unpack class Person(TypedDict): name: str age: int class Fruit(TypedDict): sort: str taste: int @overload def foo(**kwargs: Unpack[Person]) -> int: ... @overload def foo(**kwargs: Unpack[Fruit]) -> str: ... def foo(**kwargs: Any) -> Any: ... reveal_type(foo(sort="test", taste=999)) # N: Revealed type is "builtins.str" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsJoin] from typing import TypedDict from typing_extensions import Unpack class Person(TypedDict): name: str age: int def foo(*, name: str, age: int) -> None: ... def bar(**kwargs: Unpack[Person]) -> None: ... reveal_type([foo, bar]) # N: Revealed type is "builtins.list[def (*, name: builtins.str, age: builtins.int)]" reveal_type([bar, foo]) # N: Revealed type is "builtins.list[def (*, name: builtins.str, age: builtins.int)]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackKwargsParamSpec] from typing import Callable, Any, TypedDict, TypeVar, List from typing_extensions import ParamSpec, Unpack class Person(TypedDict): name: str age: int P = ParamSpec('P') T = TypeVar('T') def dec(f: Callable[P, T]) -> Callable[P, List[T]]: ... @dec def g(**kwargs: Unpack[Person]) -> int: ... reveal_type(g) # N: Revealed type is "def (*, name: builtins.str, age: builtins.int) -> builtins.list[builtins.int]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackGenericTypedDictImplicitAnyEnabled] from typing import Generic, TypedDict, TypeVar from typing_extensions import Unpack T = TypeVar("T") class TD(TypedDict, Generic[T]): key: str value: T def foo(**kwds: Unpack[TD]) -> None: ... # Same as `TD[Any]` foo(key="yes", value=42) foo(key="yes", value="ok") [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackGenericTypedDictImplicitAnyDisabled] # flags: --disallow-any-generics from typing import Generic, TypedDict, TypeVar from typing_extensions import Unpack T = TypeVar("T") class TD(TypedDict, Generic[T]): key: str value: T def foo(**kwds: Unpack[TD]) -> None: ... # E: Missing type arguments for generic type "TD" foo(key="yes", value=42) foo(key="yes", value="ok") [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [case testUnpackNoCrashOnEmpty] from typing_extensions import Unpack class C: def __init__(self, **kwds: Unpack) -> None: ... # E: Unpack[...] requires exactly one type argument class D: def __init__(self, **kwds: Unpack[int, str]) -> None: ... # E: Unpack[...] requires exactly one type argument [builtins fixtures/dict.pyi] [case testUnpackInCallableType] from typing import Callable, TypedDict from typing_extensions import Unpack class TD(TypedDict): key: str value: str foo: Callable[[Unpack[TD]], None] foo(key="yes", value=42) # E: Argument "value" has incompatible type "int"; expected "str" foo(key="yes", value="ok") bad: Callable[[*TD], None] # E: "TD" cannot be unpacked (must be tuple or TypeVarTuple) [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi]