For this function:
We currently allow any actual argument to be passed to the x parameter, since it has no annotated type. And internally to the function, we consider the type of x to be Unknown | Literal["foo"]. This is a consistent and reasonable approach that follows the gradual guarantee.
Pyright takes a different approach; it infers a "declared" type of str for the x parameter, based on the signal from the default value. So it will error on the call f(1), and it treats x internally as of type str.
Pyright's approach is parallel to how we handle attributes, after astral-sh/ruff#24531. It risks some false positives on untyped code (by not following the gradual guarantee), but probably in most cases gives better/more type information on untyped code.
I think we could consider using Pyright's approach here. It would be interesting to see what the ecosystem fallout looks like.
For this function:
We currently allow any actual argument to be passed to the
xparameter, since it has no annotated type. And internally to the function, we consider the type ofxto beUnknown | Literal["foo"]. This is a consistent and reasonable approach that follows the gradual guarantee.Pyright takes a different approach; it infers a "declared" type of
strfor thexparameter, based on the signal from the default value. So it will error on the callf(1), and it treatsxinternally as of typestr.Pyright's approach is parallel to how we handle attributes, after astral-sh/ruff#24531. It risks some false positives on untyped code (by not following the gradual guarantee), but probably in most cases gives better/more type information on untyped code.
I think we could consider using Pyright's approach here. It would be interesting to see what the ecosystem fallout looks like.