[ty] Disallow typing.TypedDict in type expressions (#19777)

## Summary

Disallow `typing.TypedDict` in type expressions.

Related reference: https://github.com/python/mypy/issues/11030

## Test Plan

New Markdown tests, checked ecosystem and conformance test impact.
This commit is contained in:
David Peter 2025-08-06 15:58:35 +02:00 committed by GitHub
parent fa711fa40f
commit b96929ee19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 2 deletions

View file

@ -375,6 +375,17 @@ reveal_type(Message.__required_keys__) # revealed: @Todo(Support for `TypedDict
msg.content
```
## Error cases
### `typing.TypedDict` is not allowed in type expressions
```py
from typing import TypedDict
# error: [invalid-type-form] "The special form `typing.TypedDict` is not allowed in type expressions."
x: TypedDict = {"name": "Alice"}
```
## Diagnostics
<!-- snapshot-diagnostics -->

View file

@ -5414,7 +5414,12 @@ impl<'db> Type<'db> {
)))
}
SpecialFormType::TypeAlias => Ok(Type::Dynamic(DynamicType::TodoTypeAlias)),
SpecialFormType::TypedDict => Ok(todo_type!("Support for `typing.TypedDict`")),
SpecialFormType::TypedDict => Err(InvalidTypeExpressionError {
invalid_expressions: smallvec::smallvec_inline![
InvalidTypeExpression::TypedDict
],
fallback_type: Type::unknown(),
}),
SpecialFormType::Literal
| SpecialFormType::Union
@ -6560,6 +6565,8 @@ enum InvalidTypeExpression<'db> {
Deprecated,
/// Same for `dataclasses.Field`
Field,
/// Same for `typing.TypedDict`
TypedDict,
/// Type qualifiers are always invalid in *type expressions*,
/// but these ones are okay with 0 arguments in *annotation expressions*
TypeQualifier(SpecialFormType),
@ -6607,6 +6614,11 @@ impl<'db> InvalidTypeExpression<'db> {
InvalidTypeExpression::Field => {
f.write_str("`dataclasses.Field` is not allowed in type expressions")
}
InvalidTypeExpression::TypedDict => {
f.write_str(
"The special form `typing.TypedDict` is not allowed in type expressions. \
Did you mean to use a concrete TypedDict or `collections.abc.Mapping[str, object]` instead?")
}
InvalidTypeExpression::TypeQualifier(qualifier) => write!(
f,
"Type qualifier `{qualifier}` is not allowed in type expressions \

View file

@ -2316,7 +2316,9 @@ impl<'db> ClassLiteral<'db> {
}
}
ClassBase::TypedDict => {
return Place::bound(todo_type!("Support for `TypedDict`")).into();
return KnownClass::TypedDictFallback
.to_instance(db)
.instance_member(db, name);
}
}
}