@@ -305,11 +305,18 @@ def field_for_schema(
305305 field = field_for_schema (newtype_supertype , default = default )
306306
307307 # enumerations
308- if type (typ ) is enum .EnumMeta :
308+ elif type (typ ) is enum .EnumMeta :
309309 import marshmallow_enum
310310
311311 field = marshmallow_enum .EnumField (typ , metadata = metadata )
312312
313+ # TypedDict
314+ elif _is_typeddict (typ ):
315+ field = marshmallow .fields .Dict (
316+ keys = marshmallow .fields .String ,
317+ values = marshmallow .fields .Raw ,
318+ )
319+
313320 # Nested dataclasses
314321 forward_reference = getattr (typ , "__forward_arg__" , None )
315322
@@ -370,6 +377,18 @@ def _get_field_default(
370377 raise TypeError (field )
371378
372379
380+ def _is_typeddict (typ : t .Any ) -> bool :
381+ # typing_inspect misses some case.
382+ # python>=3.10: use t.is_typeddict
383+ if hasattr (t , "is_typeddict" ):
384+ return t .is_typeddict (typ )
385+ # python>=3.8; <3.10: Reimplement t.is_typeddict
386+ if hasattr (t , "_TypedDictMeta" ):
387+ return isinstance (typ , t ._TypedDictMeta ) # type: ignore[attr-defined]
388+ # Fallback to typing_inspect
389+ return typing_inspect .typed_dict_keys (typ ) is not None
390+
391+
373392@attr .frozen
374393class _DesertSentinel :
375394 pass
0 commit comments