-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Subtyping and TypedDict
#1899
Comments
That's an interesting case. Pyright's type narrowing logic for the It appears that mypy does not provide type narrowing for this pattern, and maybe this is why. I'm interested in any thoughts from @JukkaL or @gvanrossum, the author and sponsor of PEP 589. |
For context, I came up with this example when someone else showed me that this type-checks in TypeScript: type A =
| { a: true, f: () => void }
| { b: true }
function f(x: A) {
if ("a" in x) {
x.f()
}
}
const x: A = { a: true, b: true }
f(x) |
I don't know what to say. I think mypy is right to flag this as an error. I also think that this pattern is much less important in Python than it is in TS -- you should probably be using real classes and isinstance(). Given that there's no real-world example underlying the example I think it wouldn't be terrible if pyright followed mypy here. PS. If you want a response from Jukka, you probably should email him directly -- I think he's one of the many people who don't pay much attention to GitHub notifications. |
For what it's worth, here is the thread where this feature was discussed for TypeScript prior to deciding to move forward with it. |
We discussed this case in more detail with the TypeScript team. As I mentioned above, there are arguments for and against making a change here. We ultimately decided to modify the current behavior in pyright to preserve type safety in all cases even if it results in some false positive errors. We concluded that if someone is using With this change, the code sample at the top of this bug report now generates an error within function from typing import Union, TypedDict, final
@final
class Foo(TypedDict):
x: int
class Bar(TypedDict):
y: str
def f(foobar: Union[Foo, Bar]):
if "y" in foobar:
print(foobar["y"].lower()) |
Thank you, that's a very reasonable solution. |
This is included in pyright 1.1.147, which I just published. It will also be included in the next release of pylance. |
@erictraut re your comment here, is this the change you ended up undoing in the commit you referenced? |
@ikonst, yes, that's correct. |
This will fail at runtime, but typechecks just fine. That's because
Foo
is not guaranteed to not have ay
key, as it can be a subtype ofFoo
. Is this as designed?The text was updated successfully, but these errors were encountered: