#4990·pyrefly

`TypedDict.copy()` falls back to `dict[str, object]`

Author: dangotbannedCreated Sep 19, 2026Updated Sep 19, 2026
Labelstypechecking

Describe the Bug

Calling copy on a TypedDict is not described in https://typing.python.org/en/latest/spec/typeddict.html#specific-operations

I've found that pyrefly, pyright and ty all disagree on how this should work with type variables.

Show code block

python
from __future__ import annotations

from typing_extensions import TypedDict, assert_type, reveal_type


class A(TypedDict, closed=True):
    a: int


class B(TypedDict, closed=True):
    b: str


a = A(a=1)
b = B(b="b")

a_copy = a.copy()
b_copy = b.copy()

assert_type(a, A)
assert_type(b, B)


def copy_bound[T: A | B](obj: T) -> T:
    result = obj.copy()  # ty: ignore[invalid-argument-type]
    reveal_type(result)
    # pyright   'Type of "result" is "A* | B*"'
    # ty        'Revealed type:      `Unknown`'
    # pyrefly   'revealed type:      dict[str, object]'
    return result

def copy_constrained[T: (A, B)](obj: T) -> T:
    result = obj.copy()
    reveal_type(result)
    # pyright   'Type of "result" is  "A* | B*"'
    # ty        'Revealed type:       `T@copy_constrained`'
    # pyrefly   'revealed type:       dict[str, object] & T'
    return result

I'm reporting here as I found the pyrefly output the most surprising. Maybe this needs to be defined in the typing spec?

My actual use case for this was a bound type variable, over a union with 20-30 members that all use closed=True.

Sandbox Link

https://pyrefly.org/sandbox/?project=v2.pVbRboIwFP2VBpNBFpXslcRk8AXLwp7EIIWqZK41o2zz73duaQno5sz0qSk97e2555x6MTLzfNNCA9QTZ20qrrBWtuHQBWsuvrSQdPE-IgapNgqwk8ByvoyDAaDcq0ZUC-qf02QRoeF6iEj-QHCbB0aZoC8OisUDtMExTgK-yDyeeUZSRV6qwxHTxZwGpDPupng_Rfru7xEUUxZjcjjFpywx6zonEy7nqpXVMo1YDAsnqwCujVhqnJE6jYmm3WschW_2MMYmIBY3NqpY1hI2rKsZYqJ9E1LP6DioqUP3dAbdTiiBPkwYBFpvdxpjn5hiagMJdWsyj5Ii8-J7Kus-83wH0kdncP_ZbC0q6jGSyPzWL_JVqk-57gHWBgToahkDKrSHIhhvlgmslQXafLHlDCkrISIN40lhiAtiovVa5m4n5T-ssHX6eFr71QydU8TuWPoTTeehM2FPdnPrX1CItNq2eNRhxnkmJ3jPBdtpfWiiMHRw9b4NhQwrVTbhCBEyytfio6jNX4XxdkyZkGyw7S1p53eyxg1_zzqfog4rLsbXNw

(Only applicable for extension issues) IDE Information

No response