Extended the "X in Y" type narrowing to support dict, defaultdict and OrderedDict classes.

This commit is contained in:
Eric Traut 2022-05-30 00:55:22 -07:00
parent 6df560a638
commit f2328237d3
3 changed files with 19 additions and 3 deletions

View File

@ -178,7 +178,7 @@ In addition to assignment-based type narrowing, Pyright supports the following t
* `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)
* `len(x) == L` and `len(x) != L` (where x is tuple and L is a literal integer)
* `x in y` or `x not in y` (where y is instance of list, set, frozenset, deque, or tuple)
* `x in y` or `x not in y` (where y is instance of list, set, frozenset, deque, tuple, dict, defaultdict, or OrderedDict)
* `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

@ -1336,11 +1336,15 @@ function narrowTypeForContains(evaluator: TypeEvaluator, referenceType: Type, co
const builtInName = containerType.details.name;
if (!['list', 'set', 'frozenset', 'deque', 'tuple'].some((name) => name === builtInName)) {
if (
!['list', 'set', 'frozenset', 'deque', 'tuple', 'dict', 'defaultdict', 'OrderedDict'].some(
(name) => name === builtInName
)
) {
return referenceType;
}
if (!containerType.typeArguments || containerType.typeArguments.length !== 1) {
if (!containerType.typeArguments || containerType.typeArguments.length < 1) {
return referenceType;
}

View File

@ -83,3 +83,15 @@ def func4(val: str | None, container: list[str]):
reveal_type(val, expected_text="str | None")
else:
reveal_type(val, expected_text="str")
def func5(x: str | None, y: int | None, z: dict[str, str]):
if x in z:
reveal_type(x, expected_text="str")
else:
reveal_type(x, expected_text="str | None")
if y not in z:
reveal_type(y, expected_text="int | None")
else:
reveal_type(y, expected_text="Never")