Generic types (like list[int]) use type arguments in square brackets to specify the type of their contents.
Invariance in Mutable Containers
Mutable container types (like list, dict, or set) are typically invariant. This means the type argument must match exactly. For example, you cannot assign a list[int] to a variable declared as list[int | None] because appending None to the latter would violate the type contract of the former.
Resolving Errors with Immutable Counterparts
To resolve assignability errors with mutable containers, switch to their immutable counterparts. Immutable types are generally more flexible with type arguments.
| Mutable Type | Immutable Type |
|---|
list | Sequence |
dict | Mapping |
set | Container |
| n/a | tuple |
Example of resolving an invariance error by using Sequence instead of list:
my_list_1: list[int] = [1, 2, 3]
# my_list_2: list[int | None] = my_list_1 # Error due to invariance
my_list_2: Sequence[int | None] = my_list_1 # No longer an error