facebook / facebook/pyrefly

`get` on `Union` with two `TypedDict`s falsely infers `str`

Open
#3,471 3 comments 0 reactions 0 assignees View on GitHub
needs-discussion typechecking
Dominant language
Rust
Stars
7k
Forks
516
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

```py
from typing import *

MovieWithYear = TypedDict('MovieWithYear', {'name': str, 'year': int})
MovieWithoutYear = TypedDict('MovieWithoutYear', {'name': str}, closed=True)
Movie = Union[MovieWithYear, MovieWithoutYear]

movie: Movie = {'name': 'Blade Runner', 'year': 1982}

movie_year = movie.get("year") or 1
reveal_type(movie_year)
```
In the above code, the lack of a `year` field on `MovieWithoutYear` makes Pyrefly falsely believe the return type of the `get` invocation on the union to be `int | str | None`, even when the `TypedDict` missing the field is explicitly set to `closed=True`.

When changing `closed=True` to `closed=False` on `MoviewWIthoutYear` it infers `object` instead of `str`, which while not a bug as far as my understanding of open TypedDicts goes (why `object` instead of `Any` though?) is still annoying when migrating from Pyright since Pyright would infer `int | None` on the same call (I believe based on my experience it just treats every `TypedDict` as closed but haven't verified, maybe add an option to assume that every TypedDict is closed for migrators from Pyright?

### Sandbox Link

https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0AqADroRAWVwA3CDADqEBgAsAmjFSU6AXjoAVZjEwARCAGMGACgDkE6XIUq1lSwBo6wS%2BlQ0YlxHTgMlK6WpI6%2BnOgMAL4AlOJSMvJKuACuDKrqWrr6RqYW1gl2yWkZTq7unt7hAZRRriZQuHAGmjqUKTBx6DYyWQCq6BC46ADaPUUO6q7jSYqp6Y4AuiIiNIV%2B41kVXj5%2BlgBCUKiYMHQASino6DBldCFhfgCMAJwAHABMUSvoa7YA%2BqFMtpfjJCGwYBYhCBAZQoTE6Lw6I8RJQYJI1FA-kxiDBzCCYADHF0QM4QGRUWAoKRCAxaFAKABiOgABVIFKp-gwOAIdBMw0gbBSlFQDCG6EIIiZAGUYKdFAwGMQ4IgAPQq8kwSnU3hsFUwdAqzC4ExwFV89ACoUisUquhgRGoSSoaCobCwXn8iCC4Wi4YI4i%2B9BwCXoMjJdAAWnRlDgYqyUIAzIRHu8oSIRjdqDHluhLlweHwDBHMBBUWYIOispYveheD4RLWGBHUQBHFKlosAaxgpAjqBMJngcCrAHd1OhLCIQHUQP3ReiAGLQGAUNBYPBEMjToA

### (Only applicable for extension issues) IDE Information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.