Aggressive type narrowing when assigning a value to a variable of a union type. #3943
Replies: 1 comment
-
This is by design, not a bug. Type narrowing is applied within an execution context, and narrowed types are not reset after call expressions. In your example, you are modifying the value of Your code sample above happens to work in mypy because of the inconsistent manner in which it applies assignment-based type narrowing. If you change Given the dynamic nature of Python, it's always possible to subvert a static type checker by modifying attributes of objects from other execution contexts. A static type checker needs to balance type safety with usability. In doing so, it needs to impose some constraints and make some assumptions about typical Python coding patterns. For example, a type checker could assume that all function calls potentially modify all global variables, so it is never safe to assume that the narrowed type of a global variable can be retained beyond a function call (or any operator, for that matter, since operators in Python invoke function calls). But that wouldn't be a very practical assumption, and it would result in many false positive errors. The pattern you're using here, where you're modifying a global variable from within a function, is somewhat fragile because the function call has non-obvious global side effects. It's a pattern I wouldn't use in my own code, and I would discourage my team members from using this approach for production code. If this were my code and I needed to create a setter function for |
Beta Was this translation helpful? Give feedback.
-
Consider the following code:
This is valid Python code, but it does not type check as Pyright aggressively narrows down the type of
foo
toNone
.The only valid workaround I could think of is to use
cast(int | None, None)
when assigning the value.Is this by design or is it a bug?
How to tell the type checker that
foo
is no longer None after a call toset_foo
?Worth noticing that mypy does not narrow the type to
None
after the assignment toNone
.I was not sure if this is in fact a bug, so I'm posting it here in Discussions.
Beta Was this translation helpful? Give feedback.
All reactions