PEP 705: Read-only TypedDict items

PEP 705 proposes supporting read-only items in TypedDicts, allowing functions that access but do not modify data in TypedDicts (e.g. service APIs) to be annotated to accept a wide range of compatible types.

The pyright playground has support for this extension, if anyone wants to experiment; instructions for using it can be found here.

Feedback appreciated!

3 Likes

Looks great! Some feedback:

  • PEP readers who are not typing experts may appreciate adding a paragraph like the following to the end of §“Abstract”, so that they don’t need to read further: (I added a similar paragraph in PEP 655 based on feedback received then.)

This PEP makes no Python grammar changes. Correct usage of read-only keys of TypedDicts is intended to be enforced only by static type checkers and need not be enforced by Python itself at runtime.

  • §“Motivation” is quite clear. :+1: §“Updating nested dicts” in particular is not something I considered when thinking about ReadOnly[] before.

  • I’d recommend adding a section to §“Specification” explaining how get_type_hints() treats ReadOnly[], similar to the callouts in PEP 655. For completeness you might consider mentioning the altered behavior of get_origin(), and get_args() as well.

    • I’d recommend that get_type_hints() strip out ReadOnly[] qualifiers by default unless include_extras=True.
  • Nit: Suggest adding the following changes in bold:

Suggested changes to the typing module documentation, in line with current practice:

  • Nit: In “Individual items can be excluded from mutate operations […]” the phrase “mutate operations” feels both overly technical and vague to me. Suggested wordsmithing to be less technical:

Individual items can be prevented from being changed by marking then as ReadOnly, allowing them only to be read.

  • Nit: For “pyright 1.1.332 fully implements this proposal.” suggest linking to the changelog or commit from pyright that indicates that it added ReadOnly support.

  • Nit: In the sentence “It would be reasonable for someone familiar with frozen, […]” it’s not clear what frozen is referring to. There are no other uses of the word “frozen” in the PEP. Did you mean readonly instead?

  • There are multiple locations in this PEP that include a Never-typed TypedDict item. (See example below.) It’s not clear to me what that even means. I suppose I don’t have specific feedback on this construction other than I find it confusing.

class B(TypedDict):
  foo: NotRequired[Never]
  • In §“Rejected alternatives” maybe it would be worth talking about why the existing Final[] qualifier couldn’t be used in place of introducing a new ReadOnly[] qualifier? I think this was discussed before but I don’t remember what was said.

  • (I did not review the formal rules in §“Type Consistency”, due to lack of energy/time)

3 Likes

Thank you for the feedback! I will look to get this all improved/clarified in the PEP. In the meantime, to some of the questions you asked:

  • Never is typing.Never. Nothing will ever match this type, so if you use it to specify a value in a dictionary, that value must be absent.
  • frozen is a parameter on dataclasses, also used to similar effect in third party libraries
  • I mention why these aren’t “final” in the opening of the rationale section. (I will still add it to the rejected alternatives section!)

@davidfstr Thanks again for the feedback! PR to address it has now merged.

typing.ReadOnly is now available in typing-extensions 4.9.0-rc1 (thanks @Jelle!)