Variable doesn't type narrow on reassignment to itself? #10781
-
|
In the following code, I expect from typing import TextIO, reveal_type
import sys
reveal_type(sys.stdout) # it says TextIO | Any (it's a MaybeNone from typeshed)
def g(stdout: TextIO):
pass
def f(stdout: TextIO | None = None):
stdout = stdout if stdout is not None else sys.stdout
g(stdout) # it says stdout is TextIO | None so it can't be assigned.
def example_function_which_is_fine():
g(sys.stdout)Code sample in pyright playground |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
|
The behavior you're seeing here is due to the |
Beta Was this translation helpful? Give feedback.
-
|
That's surprising to me. I thought it would be narrowed to Oh, I guess this makes it clearer to me (hovertext from pyright playground included as comments): def f2(stdout: TextIO | None = None):
if stdout is not None:
stdout = stdout # (parameter) stdout: TextIO = (parameter) stdout: TextIO
else:
stdout = sys.stdout # (parameter) stdout: TextIO | None = (variable) stdout: TextIO | Any
g(stdout) # it says stdout is TextIO | None so it can't be assigned.When it considers assigning sys.stdout to stdout, it says "yeah, that Any could be a None. I will keep the original type", and thus doesn't change it. Presumably, the ternary is doing this as well. The same is true also for this even simpler case: def f3(stdout: TextIO | None = None):
stdout = sys.stdout
g(stdout) # it says stdout is TextIO | None so it can't be assigned. |
Beta Was this translation helpful? Give feedback.
The behavior you're seeing here is due to the
Anytype in thesys.stdouttype definition. Since thatAnycould be aNone, it's unsafe to narrow the type ofstdoutto justTextIO. So this is intended behavior, not a bug.