Skip to content

allow consistent treatment of kwargs: Unpack[TD]#2272

Open
carljm wants to merge 1 commit intopython:mainfrom
carljm:unpacktd
Open

allow consistent treatment of kwargs: Unpack[TD]#2272
carljm wants to merge 1 commit intopython:mainfrom
carljm:unpacktd

Conversation

@carljm
Copy link
Copy Markdown
Member

@carljm carljm commented Apr 23, 2026

I think that the conformance suite (and the behavior in current type checkers) of **kwargs: Unpack[TD] is inconsistent with itself, and with the language in the spec that was added to accommodate PEP 728 (closed and extra_items).

The conformance suite asserts this (simplified for clarity):

class TD(TypedDict):
	v1: int

def f(**kwargs: Unpack[TD]): ...

f(v1=1, v2=2) # E: TD doesn't contain `v2`

But the spec (since PEP 728) says that if TD allows extra items, then those should be accepted in calls. And it also says that a TypedDict without an explicit closed or extra_items parameter usually behaves as if it has extra_items of type ReadOnly[object].

Thus I think the extra argument in the call above should be allowed, even though current type checkers disallow it.

Some type checkers (pyright and pyrefly) allow this call:

class TD2(TD1):
    v2: int

def _(td2: TD2):
    f(**td2)

It seems clear that this second call should be allowed, because TD2 is a subtype of TD1 and assignable to it, so **td2 should be acceptable for **kwargs: Unpack[TD1]. But if this call (which definitely provides a keyword argument v2) is allowed, then it's inconsistent not to also allow the above call that explicitly provides v2.

If f should not accept arbitrary additional keyword arguments, it should instead use **kwargs: Unpack[ClosedTD], where ClosedTD is closed=True.

In addition, the spec and conformance suite now require assignability of callables using **kwargs: Unpack[TD] to behave in a way that accounts for this possibility of additional keyword arguments being passed. It's inconsistent to require callable assignability to account for this, yet not allow calls to actually make use of it. In ty, we want to implement Unpack[TD] in such a way that it can be treated as simply syntax sugar, by transforming **kwargs: Unpack[TD] into a set of explicit typed keyword arguments and (possibly, for a non-closed TypedDict) a preserved **kwargs parameter. I think this approach is clearly desirable for consistent and predictable behavior, as well as for simplicity of implementation. But the current conformance suite is inconsistent with itself in a way that makes such an implementation impossible.

Personally I believe the # E on this line should simply be removed, and conformant implementation should be required to allow this call. But I'm proposing here to simply relax the assertion to # E? in order to respect backward compatibility and not put existing type-checkers into non-conformance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic: conformance tests Issues with the conformance test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant