Generic type aliases
Type aliases can be generic. In this case they can be used in two ways:Subscripted aliases are equivalent to original types with substituted typevariables, so the number of type arguments must match the number of free type variablesin the generic type alias. Unsubscripted aliases are treated as original types with freevariables replaced with Any
. Examples (following PEP 484: Type aliases):
- from typing import TypeVar, Iterable, Tuple, Union, Callable
- S = TypeVar('S')
- TInt = Tuple[int, S]
- UInt = Union[S, int]
- CBack = Callable[..., S]
- def response(query: str) -> UInt[str]: # Same as Union[str, int]
- ...
- def activate(cb: CBack[S]) -> S: # Same as Callable[..., S]
- ...
- table_entry: TInt # Same as Tuple[int, Any]
- T = TypeVar('T', int, float, complex)
- Vec = Iterable[Tuple[T, T]]
- def inproduct(v: Vec[T]) -> T:
- return sum(x*y for x, y in v)
- def dilate(v: Vec[T], scale: T) -> Vec[T]:
- return ((x * scale, y * scale) for x, y in v)
- v1: Vec[int] = [] # Same as Iterable[Tuple[int, int]]
- v2: Vec = [] # Same as Iterable[Tuple[Any, Any]]
- v3: Vec[int, int] = [] # Error: Invalid alias, too many type arguments!
Type aliases can be imported from modules just like other names. Analias can also target another alias, although building complex chainsof aliases is not recommended – this impedes code readability, thusdefeating the purpose of using aliases. Example:
- from typing import TypeVar, Generic, Optional
- from example1 import AliasType
- from example2 import Vec
- # AliasType and Vec are type aliases (Vec as defined above)
- def fun() -> AliasType:
- ...
- T = TypeVar('T')
- class NewVec(Vec[T]):
- ...
- for i, j in NewVec[int]():
- ...
- OIntVec = Optional[Vec[int]]
Note
A type alias does not define a new type. For generic type aliasesthis means that variance of type variables used for alias definition does notapply to aliases. A parameterized generic alias is treated simply as an originaltype with the corresponding type variables substituted.