Skip to content

[ty] Add support for functional TypedDict(...)#24092

Closed
charliermarsh wants to merge 1 commit intomainfrom
charlie/functional-typed
Closed

[ty] Add support for functional TypedDict(...)#24092
charliermarsh wants to merge 1 commit intomainfrom
charlie/functional-typed

Conversation

@charliermarsh
Copy link
Copy Markdown
Member

Summary

Closes astral-sh/ty#3095.

@charliermarsh charliermarsh added the ty Multi-file analysis & type inference label Mar 21, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 21, 2026

Typing conformance results

The percentage of diagnostics emitted that were expected errors decreased from 85.38% to 85.34%. The percentage of expected errors that received a diagnostic increased from 78.70% to 78.98%. The number of fully passing files improved from 64/132 to 65/132.

Summary

How are test cases classified?

Each test case represents one expected error annotation or a group of annotations sharing a tag. Counts are per test case, not per diagnostic — multiple diagnostics on the same line count as one. Required annotations (E) are true positives when ty flags the expected location and false negatives when it does not. Optional annotations (E?) are true positives when flagged but true negatives (not false negatives) when not. Tagged annotations (E[tag]) require ty to flag exactly one of the tagged lines; tagged multi-annotations (E[tag+]) allow any number up to the tag count. Flagging unexpected locations counts as a false positive.

Metric Old New Diff Outcome
True Positives 835 838 +3 ⏫ (✅)
False Positives 143 144 +1 ⏫ (❌)
False Negatives 226 223 -3 ⏬ (✅)
Total Diagnostics 1055 1060 +5
Precision 85.38% 85.34% -0.04% ⏬ (❌)
Recall 78.70% 78.98% +0.28% ⏫ (✅)
Passing Files 64/132 65/132 +1 ⏫ (✅)

Test file breakdown

4 files altered
File True Positives False Positives False Negatives Status
typeddicts_alt_syntax.py 2 (+2) ✅ 0 3 (-1) ✅ 📈 Improving
typeddicts_extra_items.py 9 (+1) ✅ 22 (+1) ❌ 19 (-1) ✅ ➡️ Neutral
typeddicts_readonly.py 6 (+1) ✅ 0 0 (-1) ✅ ✅ Newly Passing 🎉
typeddicts_type_consistency.py 9 (-1) ❌ 0 0 ✅ Still Passing
Total (all files) 838 (+3) ✅ 144 (+1) ❌ 223 (-3) ✅ 65/132

True positives added (3)

3 diagnostics
Test case Diff

typeddicts_alt_syntax.py:35

+error[unknown-argument] Argument `other` does not match any known parameter of function `TypedDict`
+error[invalid-type-form] Boolean literals are not allowed in this context in a type expression

typeddicts_extra_items.py:22

+error[invalid-key] Unknown key "year" for TypedDict `MovieFunctional`

typeddicts_readonly.py:36

+error[invalid-assignment] Cannot assign to key "members" on TypedDict `Band2`: key is marked read-only

False positives added (1)

1 diagnostic
Test case Diff

typeddicts_extra_items.py:21

+error[invalid-key] Unknown key "novel_adaptation" for TypedDict `MovieFunctional`

Optional Diagnostics Added (1)

1 diagnostic
Test case Diff

typeddicts_alt_syntax.py:45

+error[invalid-argument-type] Invalid argument to key "year" with declared type `int` on TypedDict `Movie2`: value of type `Literal[""]`

Optional Diagnostics Removed (1)

1 diagnostic
Test case Diff

typeddicts_type_consistency.py:101

-error[invalid-assignment] Object of type `Unknown | None` is not assignable to `str`

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 21, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 705.17MB 711.76MB +0.93% (6.58MB)
sphinx 263.10MB 265.06MB +0.74% (1.96MB)
trio 116.13MB 116.80MB +0.58% (690.23kB)
flake8 48.16MB 48.33MB +0.36% (178.06kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
infer_definition_types 90.88MB 96.59MB +6.28% (5.71MB)
infer_deferred_types 14.56MB 15.44MB +6.05% (901.80kB)
is_redundant_with_impl 5.58MB 5.58MB -0.06% (3.47kB)
Type<'db>::class_member_with_policy_ 17.73MB 17.73MB +0.02% (3.43kB)
infer_expression_types_impl 56.22MB 56.21MB -0.01% (2.98kB)
Type<'db>::member_lookup_with_policy_ 16.27MB 16.26MB -0.01% (2.33kB)
infer_expression_type_impl 14.00MB 14.00MB -0.02% (2.28kB)
StaticClassLiteral<'db>::implicit_attribute_inner_::interned_arguments 5.24MB 5.24MB +0.03% (1.59kB)
is_redundant_with_impl::interned_arguments 5.34MB 5.34MB -0.03% (1.38kB)
StaticClassLiteral<'db>::implicit_attribute_inner_ 10.06MB 10.06MB +0.01% (1.31kB)
CallableType 1.70MB 1.70MB +0.05% (864.00B)
IntersectionType 2.28MB 2.28MB -0.03% (800.00B)
Type<'db>::try_call_dunder_get_ 10.67MB 10.67MB +0.01% (776.00B)
TypedDictSpec 0.00B 628.00B +628.00B (new)
all_negative_narrowing_constraints_for_expression 2.81MB 2.81MB -0.02% (612.00B)
... 35 more

sphinx

Name Old New Diff Outcome
infer_definition_types 24.44MB 26.12MB +6.88% (1.68MB)
infer_deferred_types 5.60MB 5.88MB +4.96% (284.50kB)
known_class_to_class_literal 6.59kB 6.45kB -2.08% (140.00B)
Type<'db>::try_call_dunder_get_ 4.95MB 4.95MB -0.00% (84.00B)
KnownClassArgument 2.46kB 2.41kB -2.22% (56.00B)

trio

Name Old New Diff Outcome
infer_definition_types 7.52MB 8.07MB +7.31% (562.82kB)
infer_deferred_types 2.36MB 2.49MB +5.26% (127.41kB)

flake8

Name Old New Diff Outcome
infer_definition_types 1.95MB 2.09MB +7.09% (141.31kB)
infer_deferred_types 690.39kB 727.14kB +5.32% (36.75kB)

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 21, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-await 0 40 0
invalid-argument-type 32 3 3
invalid-key 11 3 0
missing-typed-dict-key 12 1 0
unused-type-ignore-comment 0 13 0
unresolved-attribute 0 7 0
invalid-assignment 5 0 0
invalid-method-override 5 0 0
invalid-return-type 1 3 0
no-matching-overload 1 0 0
Total 67 70 3

Large timing changes:

Project Old Time New Time Change
cibuildwheel 0.07s 0.11s +53%

Changes in flaky projects detected. Raw diff output excludes flaky projects; see the HTML report for details.

Raw diff (98 changes)
alerta (https://github.com/alerta/alerta)
+ alerta/utils/logging.py:48:25 error[invalid-key] Unknown key "()" for TypedDict `_FormatterConfigurationTypedDict`
+ alerta/utils/logging.py:57:25 error[invalid-key] Unknown key "()" for TypedDict `_FormatterConfigurationTypedDict`
+ alerta/utils/logging.py:60:25 error[invalid-key] Unknown key "()" for TypedDict `_FormatterConfigurationTypedDict`
+ alerta/utils/logging.py:61:25 error[invalid-key] Unknown key "facility" for TypedDict `_FormatterConfigurationTypedDict`

dragonchain (https://github.com/dragonchain/dragonchain)
+ dragonchain/lib/dto/api_key_model.py:175:9 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `permissions_doc`, found `permissions_doc | dict[str, str | bool | dict[Unknown, Unknown]]`
+ dragonchain/lib/dto/api_key_model.py:209:9 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `permissions_doc`, found `permissions_doc | dict[str, str | bool | dict[Unknown, Unknown]]`
+ dragonchain/transaction_processor/level_3_actions_utest.py:247:86 error[invalid-argument-type] Argument to function `verify_blocks` is incorrect: Expected `L1Headers`, found `dict[str, str]`
+ dragonchain/webserver/helpers_utest.py:169:47 error[invalid-argument-type] Argument to function `verify_custom_indexes_options` is incorrect: Expected `Iterable[custom_index]`, found `list[dict[str, str]]`
+ dragonchain/webserver/helpers_utest.py:169:48 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/webserver/helpers_utest.py:172:47 error[invalid-argument-type] Argument to function `verify_custom_indexes_options` is incorrect: Expected `Iterable[custom_index]`, found `list[dict[str, str]]`
+ dragonchain/webserver/helpers_utest.py:172:48 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/webserver/helpers_utest.py:175:47 error[invalid-argument-type] Argument to function `verify_custom_indexes_options` is incorrect: Expected `Iterable[custom_index]`, found `list[dict[str, str]]`
+ dragonchain/webserver/helpers_utest.py:175:48 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:66 error[invalid-argument-type] Argument to function `create_api_key_v1` is incorrect: Expected `permissions_doc | None`, found `dict[str, str]`
+ dragonchain/webserver/lib/api_keys_utest.py:48:87 error[missing-typed-dict-key] Missing required key 'default_allow' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:87 error[missing-typed-dict-key] Missing required key 'permissions' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:87 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:48:88 error[invalid-key] Unknown key "wind" for TypedDict `permissions_doc`
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[invalid-argument-type] Argument to function `update_api_key_v1` is incorrect: Expected `permissions_doc | None`, found `dict[str, str]`
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[missing-typed-dict-key] Missing required key 'default_allow' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[missing-typed-dict-key] Missing required key 'permissions' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:91:59 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `permissions_doc` constructor
+ dragonchain/webserver/lib/api_keys_utest.py:91:60 error[invalid-key] Unknown key "definitely" for TypedDict `permissions_doc`
+ dragonchain/lib/database/redisearch_utest.py:71:55 error[invalid-argument-type] Argument to function `create_transaction_index` is incorrect: Expected `Iterable[custom_index] | None`, found `list[dict[str, str]]`
+ dragonchain/lib/database/redisearch_utest.py:71:56 error[missing-typed-dict-key] Missing required key 'options' in TypedDict `custom_index` constructor
+ dragonchain/transaction_processor/level_4_actions_utest.py:73:63 error[invalid-argument-type] Argument to function `verify_blocks` is incorrect: Expected `L1Headers`, found `dict[str, int | str]`
+ dragonchain/transaction_processor/level_4_actions_utest.py:73:73 error[invalid-argument-type] Invalid argument to key "dc_id" with declared type `str` on TypedDict `L1Headers`: value of type `Literal[123]`
+ dragonchain/transaction_processor/level_4_actions_utest.py:73:90 error[invalid-argument-type] Invalid argument to key "block_id" with declared type `str` on TypedDict `L1Headers`: value of type `Literal[124]`

graphql-core (https://github.com/graphql-python/graphql-core)
- tests/utilities/test_build_client_schema.py:90:53 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:498:54 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:673:44 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:682:42 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:987:60 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- tests/utilities/test_build_client_schema.py:1002:55 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive

hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- src/hydra_zen/wrapper/_implementations.py:1572:89 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive

isort (https://github.com/pycqa/isort)
- isort/output.py:587:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `@Todo(Functional TypedDicts) | None | list[Unknown]`
+ isort/output.py:587:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `Any | None | list[Unknown]`
- isort/output.py:597:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `@Todo(Functional TypedDicts) | None | list[Unknown]`
+ isort/output.py:597:25 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `Any | None | list[Unknown]`
- isort/output.py:605:29 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `@Todo(Functional TypedDicts) | None | list[Unknown]`
+ isort/output.py:605:29 error[invalid-argument-type] Argument to function `import_statement` is incorrect: Expected `Sequence[str]`, found `Any | None | list[Unknown]`

meson (https://github.com/mesonbuild/meson)
- mesonbuild/cargo/manifest.py:330:16 error[missing-typed-dict-key] Missing required key 'workspace' in TypedDict `FromWorkspace` constructor
- mesonbuild/cargo/manifest.py:330:17 error[invalid-key] Unknown key "version" for TypedDict `FromWorkspace`
- mesonbuild/cargo/manifest.py:542:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `LibTarget`, found `dict[Unknown, Unknown]`
- mesonbuild/cargo/manifest.py:557:54 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `BuildTarget`, found `dict[str, str]`
- mesonbuild/cargo/manifest.py:563:54 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `BuildTarget`, found `dict[str, str]`
+ mesonbuild/cargo/manifest.py:336:22 error[no-matching-overload] No overload of function `_depv_to_dep` matches arguments
+ unittests/cargotests.py:332:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:333:33 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, dict[str, str] | FromWorkspace]`
+ unittests/cargotests.py:333:45 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `Package` constructor
+ unittests/cargotests.py:340:33 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, dict[str, str]]`
+ unittests/cargotests.py:340:45 error[missing-typed-dict-key] Missing required key 'version' in TypedDict `Package` constructor
+ unittests/cargotests.py:350:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:364:40 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:400:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:417:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:441:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:457:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:497:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:504:38 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:515:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:549:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
+ unittests/cargotests.py:569:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `Manifest`, found `dict[str, object]`
- unittests/cargotests.py:379:68 error[invalid-key] Unknown key "optional" for TypedDict `FromWorkspace`
+ unittests/cargotests.py:379:48 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `FromWorkspace | Dependency | str`, found `dict[str, bool]`
- unittests/cargotests.py:387:62 error[invalid-key] Unknown key "features" for TypedDict `FromWorkspace`
+ unittests/cargotests.py:387:42 error[invalid-argument-type] Argument to bound method `from_raw` is incorrect: Expected `FromWorkspace | Dependency | str`, found `dict[str, bool | list[str]]`

operator (https://github.com/canonical/operator)
+ ops/_private/harness.py:1640:9 error[invalid-assignment] Invalid subscript assignment with key of type `tuple[str | None, int | None]` and value of type `dict[str, list[dict[str, str | list[dict[str, str]]]] | list[str]]` on object of type `dict[tuple[str | None, int | None], _NetworkDict]`
+ ops/_private/harness.py:3355:38 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `str | LayerDict | None`, found `str | (LayerDict & Top[dict[Unknown, Unknown]]) | (Layer & Top[dict[Unknown, Unknown]])`
- ops/model.py:3738:40 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ ops/model.py:3737:16 error[invalid-return-type] Return type does not match returned value: expected `_StatusDict`, found `dict[str, str]`
- ops/pebble.py:630:58 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:720:58 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:789:58 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:1170:40 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- ops/pebble.py:1188:40 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ ops/pebble.py:884:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:946:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:963:28 error[invalid-assignment] Object of type `(ServiceDict & ~AlwaysFalsy) | dict[Unknown, Unknown]` is not assignable to `ServiceDict`
+ ops/pebble.py:1033:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:1101:26 error[invalid-assignment] Object of type `(CheckDict & ~AlwaysFalsy) | dict[Unknown, Unknown]` is not assignable to `CheckDict`
+ ops/pebble.py:1148:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:1171:27 error[invalid-key] TypedDict `ExecDict` can only be subscripted with a string literal key, got key of type `str`.
+ ops/pebble.py:1173:27 error[invalid-key] TypedDict `ExecDict` can only be subscripted with a string literal key, got key of type `str & ~Literal["environment"]`.
+ ops/pebble.py:1189:27 error[invalid-key] TypedDict `HttpDict` can only be subscripted with a string literal key, got key of type `str`.
+ ops/pebble.py:1191:27 error[invalid-key] TypedDict `HttpDict` can only be subscripted with a string literal key, got key of type `str & ~Literal["headers"]`.
+ ops/pebble.py:1204:22 error[invalid-key] TypedDict `TcpDict` can only be subscripted with a string literal key, got key of type `str`.
+ ops/pebble.py:1262:30 error[invalid-assignment] Object of type `(LogTargetDict & ~AlwaysFalsy) | dict[Unknown, Unknown]` is not assignable to `LogTargetDict`
+ ops/pebble.py:1286:9 error[invalid-method-override] Invalid override of method `__eq__`: Definition is incompatible with `object.__eq__`
+ ops/pebble.py:2103:23 error[invalid-argument-type] Invalid argument to key "access" with declared type `Literal["untrusted", "metrics", "read", "admin"]` on TypedDict `IdentityDict`: value of type `str`
+ ops/pebble.py:2556:36 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `str | LayerDict | None`, found `(LayerDict & Top[dict[Unknown, Unknown]]) | (Layer & Top[dict[Unknown, Unknown]])`

ppb-vector (https://github.com/ppb/ppb-vector)
- tests/test_length.py:41:20 error[unresolved-attribute] Object of type `int | float` has no attribute `length`
- tests/test_project.py:50:8 error[unresolved-attribute] Object of type `int | float` has no attribute `isclose`
- tests/test_scalar_multiplication.py:10:28 error[unresolved-attribute] Object of type `int | float` has no attribute `x`
- tests/test_scalar_multiplication.py:11:28 error[unresolved-attribute] Object of type `int | float` has no attribute `y`
- tests/test_scalar_multiplication.py:19:12 error[unresolved-attribute] Object of type `int | float` has no attribute `isclose`
- tests/test_scalar_multiplication.py:24:12 error[unresolved-attribute] Object of type `int | float` has no attribute `isclose`
- tests/test_scalar_multiplication.py:32:20 error[unresolved-attribute] Object of type `int | float` has no attribute `length`
- ppb_vector/__init__.py:567:16 error[invalid-return-type] Return type does not match returned value: expected `Vector`, found `int | float`
- ppb_vector/__init__.py:588:16 error[invalid-return-type] Return type does not match returned value: expected `tuple[Vector, Vector]`, found `tuple[int | float, Vector]`

rotki (https://github.com/rotki/rotki)
+ rotkehlchen/logging.py:210:23 error[invalid-argument-type] Invalid argument to key "formatters" with declared type `dict[str, _FormatterConfigurationTypedDict | dict[str, Any]]` on TypedDict `_DictConfigArgs`: value of type `dict[str, dict[str, str]]`

Full report with detailed diff (timing results)

@charliermarsh charliermarsh force-pushed the charlie/functional-typed branch from 8eafd25 to bc66412 Compare March 21, 2026 02:32
charliermarsh added a commit that referenced this pull request Mar 23, 2026
## Summary

This TODO led to some false positives in
#24092, so putting this up
separately.

I believe the ecosystem diagnostics are false positives (and the
Pydantic diagnostics in particular already have `# pyright: ignore`).
@charliermarsh charliermarsh force-pushed the charlie/functional-typed branch from 34f9e2b to 758a457 Compare March 24, 2026 01:10
@charliermarsh charliermarsh force-pushed the charlie/functional-typed branch from 758a457 to 9d2bc1d Compare March 24, 2026 02:12
@charliermarsh
Copy link
Copy Markdown
Member Author

Closing in favor of this stack: #24174

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

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Functional TypedDict syntax

1 participant