Difference between defining typing.Dict and dict?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Since Python 3.9, dict[str, int] and typing.Dict[str, int] are functionally identical for type annotations — both describe a dictionary with string keys and integer values. Before Python 3.9, only typing.Dict supported subscripting (Dict[str, int]), while dict[str, int] was a TypeError. The modern recommendation is to use the built-in dict (lowercase) for type hints in Python 3.9+ and reserve typing.Dict for code that must support Python 3.8 or earlier. This change was introduced by PEP 585 to simplify type annotations by eliminating the need to import from typing.
The Historical Problem
PEP 585 Built-in Generics (Python 3.9+)
| typing module | Built-in (3.9+) |
typing.Dict[K, V] | dict[K, V] |
typing.List[T] | list[T] |
typing.Tuple[T, ...] | tuple[T, ...] |
typing.Set[T] | set[T] |
typing.FrozenSet[T] | frozenset[T] |
typing.Type[T] | type[T] |
Using from __future__ import annotations (Python 3.7+)
With from __future__ import annotations, all annotations become strings. The dict[str, int] syntax is never evaluated at runtime, so it works even on Python versions that do not support built-in generics.
Runtime Behavior Differences
When to Use Which
Typing-Only Imports That Are No Longer Needed
Common Pitfalls
- Using
dict[str, int]on Python 3.8 without__future__: This raisesTypeError: 'type' object is not subscriptableat runtime. Either addfrom __future__ import annotationsor usetyping.Dictfor Python 3.8 compatibility. - Using generic types with
isinstance():isinstance(obj, dict[str, int])raisesTypeErrorin all Python versions. Generic aliases cannot be used for runtime type checking. Useisinstance(obj, dict)without type parameters. - Mixing
typing.Dictanddictinconsistently: UsingDictin some annotations anddictin others is not a bug but hurts readability. Pick one style per project and enforce it with a linter (ruff, flake8-pep585). - Forgetting that
__future__annotations are strings: Withfrom __future__ import annotations, annotations are not evaluated at runtime. Code that accessesfunc.__annotations__or usestyping.get_type_hints()may behave differently. Pydantic v1 and some decorators require real type objects, not strings. - Removing
typingimports needed for runtime features:typing.TypeVar,typing.Generic,typing.Protocol,typing.Literal, andtyping.Annotatedhave no built-in equivalents. Only container types (Dict,List,Tuple,Set) can be replaced with built-in generics.
Summary
- Python 3.9+: use
dict[K, V]instead oftyping.Dict[K, V]— no import needed - Python 3.7-3.8: use
from __future__ import annotationsto enabledict[K, V]syntax - Python 3.6-3.8 without
__future__: usetyping.Dict[K, V] dict[K, V]andDict[K, V]are equal for type checking but are different runtime objects- Neither
dict[K, V]norDict[K, V]can be used withisinstance()— use the plaindicttype - The same pattern applies to
list,tuple,set,frozenset, andtype(PEP 585)
Related reading
- Difference between del, remove, and pop on lists in Python
- Difference between del, remove, and pop on lists in Python
- Difference between except and except Exception as e
- Difference between exit0 and exit1 in Python
- Difference between exit and sys.exit in Python
- Difference between Faust vs Kafka-python
- Difference between filter and filter_by in SQLAlchemy
- Difference between modelx and model.predictx in Keras?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.