How do I annotate types in a for-loop?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python does not support type annotations directly on for loop variables in the loop header. Instead, you declare the type on a separate line before the loop, or rely on type inference from the iterable's type hint. Type checkers like mypy infer the loop variable type automatically when the iterable is properly annotated, so explicit annotation is rarely needed.
The Problem
Python's for statement does not accept inline type annotations on the loop variable. The grammar simply does not support it.
Method 1: Annotate Before the Loop
The x: int declaration tells type checkers that x is an int. The for loop then assigns to x without needing its own annotation. This is the officially supported approach.
Method 2: Let Type Inference Work
When the iterable is properly typed, type checkers infer the loop variable automatically:
This is the most common approach. If the iterable has a proper type, the loop variable type is inferred.
Method 3: Type Hint the Function Returning the Iterable
Annotating with Tuple Unpacking
Annotating with enumerate and zip
In practice, mypy infers these correctly without the pre-declarations if the input lists are typed.
Annotating Dict Iteration
Using cast() for Complex Cases
When the iterable's type is too broad:
cast() does not change runtime behavior — it only tells the type checker to treat the value as the specified type.
Custom Iterables
The return type of __iter__ determines the loop variable type. This is the standard pattern for custom iterables.
Type Checking with mypy
Common Pitfalls
- Inline annotation syntax:
for x: int in range(10)is aSyntaxError. Python does not support type annotations in theforheader. Annotate on a separate line before the loop. - Over-annotating: If your iterable is properly typed, the loop variable type is inferred automatically. Adding redundant annotations clutters the code. Only annotate when the type is ambiguous or when you want to constrain it.
- Scope of loop variables: In Python, the loop variable persists after the loop ends. The pre-loop
x: intannotation applies both inside and after the loop. - Using
assert isinstance()instead of annotations:assert isinstance(item, int)narrows the type at runtime (and for type checkers), but it adds runtime overhead. Use type annotations for static checking andisinstanceonly when you need runtime validation. - Ignoring
Anytypes: Libraries without type stubs returnAny. Loop variables fromAnyiterables areAny. Usecast()or type: ignore comments when you know the actual type.
Summary
- Python does not support
for x: int in ...syntax — annotate on a separate line:x: int - Type checkers infer loop variable types from the iterable's type annotation automatically
- Annotate the iterable (function return type, variable type) rather than the loop variable for cleaner code
- Use
cast()when the inferred type is too broad (e.g.,Anyfrom untyped libraries) - Pre-loop annotations are only needed when inference fails or you want to explicitly constrain the type

