[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 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 ## Diagnostics
<!-- snapshot-diagnostics --> <!-- snapshot-diagnostics -->

View file

@ -5414,7 +5414,12 @@ impl<'db> Type<'db> {
))) )))
} }
SpecialFormType::TypeAlias => Ok(Type::Dynamic(DynamicType::TodoTypeAlias)), 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::Literal
| SpecialFormType::Union | SpecialFormType::Union
@ -6560,6 +6565,8 @@ enum InvalidTypeExpression<'db> {
Deprecated, Deprecated,
/// Same for `dataclasses.Field` /// Same for `dataclasses.Field`
Field, Field,
/// Same for `typing.TypedDict`
TypedDict,
/// Type qualifiers are always invalid in *type expressions*, /// Type qualifiers are always invalid in *type expressions*,
/// but these ones are okay with 0 arguments in *annotation expressions* /// but these ones are okay with 0 arguments in *annotation expressions*
TypeQualifier(SpecialFormType), TypeQualifier(SpecialFormType),
@ -6607,6 +6614,11 @@ impl<'db> InvalidTypeExpression<'db> {
InvalidTypeExpression::Field => { InvalidTypeExpression::Field => {
f.write_str("`dataclasses.Field` is not allowed in type expressions") 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!( InvalidTypeExpression::TypeQualifier(qualifier) => write!(
f, f,
"Type qualifier `{qualifier}` is not allowed in type expressions \ "Type qualifier `{qualifier}` is not allowed in type expressions \

View file

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