The code type-checks. Since it is impossible for any variable to take a value of type Never, the type signature of blah is equivalent to str -> None. The function's body is valid when s is annotated with type str, so it should be valid when annotated with Never | str.
Actual Behavior
main.py:5: error: Unsupported left operand type for + ("Never") [operator]
main.py:5: note: Left operand is of type "Never | str"
Found 1 error in 1 file (checked 1 source file)
Your Environment
Python 3.12
MyPy 1.15.0, invocation as performed in the Playground
Background
Pyright appears to do the right thing here: it accepts this code.
I ran into this when implementing this pattern, which is me placing types around something I found untyped in the wild:
That way, MyType has type _MyProtocol[foo.Foo] | _MyProtocol[Never], allowing a type-level discrimination of whether the foo functionality is present or not.
Activity
jorenham commented on Mar 10, 2025
According to the typing spec:
And since Never <: T for all types T, Never | T is indeed equivalent to T.
sterliakov commented on Mar 10, 2025
A safe casting (no Any, no cast) allows your code:
This means mypy models assignability rules correctly, but does not attempt filtering Never out of a union.
(I can also recommend the code above as a workaround for now: it's definitely safe and won't mask any future error)
A5rocks commented on Mar 11, 2025
Technically #18707 fixes this (I introduced a bunch of changes around Never) but maybe mypy should more aggressively simplify unions too.