Improved handling of x in y type guard to handle the case where y is a tuple.

This commit is contained in:
Eric Traut 2021-12-08 00:17:46 -08:00
parent c7e4d3badf
commit e267b8adec
3 changed files with 14 additions and 3 deletions

View File

@ -156,7 +156,7 @@ In addition to assignment-based type narrowing, Pyright supports the following t
* `x[K] == V` and `x[K] != V` (where K and V are literal expressions and x is a type that is distinguished by a TypedDict field with a literal type)
* `x[I] == V` and `x[I] != V` (where I and V are literal expressions and x is a known-length tuple that is distinguished by the index indicated by I)
* `x[I] is None` and `x[I] is not None` (where I is a literal expression and x is a known-length tuple that is distinguished by the index indicated by I)
* `x in y` (where y is instance of list, set, frozenset, or deque)
* `x in y` (where y is instance of list, set, frozenset, deque, or tuple)
* `S in D` and `S not in D` (where S is a string literal and D is a TypedDict)
* `isinstance(x, T)` (where T is a type or a tuple of types)
* `issubclass(x, T)` (where T is a type or a tuple of types)

View File

@ -954,7 +954,7 @@ function narrowTypeForContains(evaluator: TypeEvaluator, referenceType: Type, co
const builtInName = containerType.details.name;
if (!['list', 'set', 'frozenset', 'deque'].some((name) => name === builtInName)) {
if (!['list', 'set', 'frozenset', 'deque', 'tuple'].some((name) => name === builtInName)) {
return referenceType;
}

View File

@ -1,6 +1,6 @@
# This sample tests type narrowing for the "in" operator.
from typing import Optional, Union
from typing import Literal, Optional, Union
import random
@ -38,3 +38,14 @@ if y in [2]:
# This should generate an error because y should
# be narrowed to an int.
verify_str(y)
def func1(x: Optional[Union[int, str]]):
if x in (1, 2):
t1: Literal["int"] = reveal_type(x)
if x in (1, "2"):
t2: Literal["int | str"] = reveal_type(x)
if x in (1, None):
t3: Literal["int | None"] = reveal_type(x)