Python 3.5+

Since Python 3.5 you may use typing module.

Quoting docs, A type alias is defined by assigning the type to the alias:

Copy# Python 3.5-3.8
from typing import List
Vector = List[float]

# Python 3.9+
Vector = list[float] # No import needed, lower case l

To learn more about enforcing types in Python you may want to get familiar with PEPs: PEP483 and PEP484.

Python historically was using duck-typing instead of strong typing and hadn't built-in way of declaring types before 3.5 release.

Answer from Łukasz Rogalski on Stack Overflow
🌐
Python
typing.python.org › en › latest › spec › aliases.html
Type aliases — typing documentation
class PacketId: def __init__(self, major: int, minor: int) -> None: self._major = major self._minor = minor TcpPacketId = NewType('TcpPacketId', PacketId) packet = PacketId(100, 100) tcp_packet = TcpPacketId(packet) # OK tcp_packet = TcpPacketId(127, 0) # Fails in type checker and at runtime · Both isinstance and issubclass, as well as subclassing will fail for NewType('Derived', Base), since the object returned by a call to NewType is not a class. See also NewType() and type aliases for a discussion of how NewType interacts with protocol definitions.
🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
Added in version 3.10. class typing.TypeAliasType(name, value, *, type_params=())¶ · The type of type aliases created through the type statement.
🌐
Python
peps.python.org › pep-0613
PEP 613 – Explicit Type Aliases | peps.python.org
With explicit aliases, the type checker has enough information to error on the actual definition of the bad type alias, and explain why: that MyGeneric(int) and InvalidType are not valid types. When the value expression is no longer evaluated as a global value, unactionable type errors on all usages of MyType across the codebase can be suppressed. class Foo: x = ClassName y: TypeAlias = ClassName z: Type[ClassName] = ClassName
🌐
GitHub
github.com › python › mypy › issues › 9238
Type aliases in class definitions · Issue #9238 · python/mypy
June 26, 2020 - The use of type aliases in classes seems both like a pretty legitimate use case to me (consider for example the ability to have an input type for the class as an attribute of the class as above) and also seems consistent with both the typing documentation and mypy's documentation, neither of which seem to mention that type aliases can only appear at the top level (only that they need to be plain assignments, as they are in the above code).
Published   Jul 31, 2020
🌐
Real Python
realpython.com › ref › glossary › type-alias
type alias | Python Glossary – Real Python
In Python, a type alias allows you to create an alternative name for an existing type.
🌐
Mypy
mypy.readthedocs.io › en › stable › kinds_of_types.html
Kinds of types - mypy 1.19.1 documentation
Aliases defined using the type statement have these properties, which distinguish them from implicit type aliases: The definition may contain forward references without having to use string literal escaping, since it is evaluated lazily. The alias can be used in type annotations, type arguments, and casts, but it can’t be used in contexts which require a class object.
🌐
TestDriven.io
testdriven.io › tips › e2b4b882-eac8-4231-a64f-219e98b084a4
Tips and Tricks - Python type hints - creating a type alias | TestDriven.io
You can create a type alias to make your code more readable. from typing import List Vector = List[float] def scale(scalar: float, vector: Vector) -> Vector: return [scalar * num for num in vector]
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › how to type hint a class alias
r/learnpython on Reddit: How to type hint a class alias
July 19, 2024 -

I have a Python library which has (in my development branch on git) recently had a facelift. It has bindings to Rust, and due to a lot of mostly aesthetic reasons, I now have two versions of every class, a version A and a version B. For instance, if I had

class ClassA:
    pass # lots of stuff here

I now have

class ClassB:
    pass # lots of stuff here

class ClassC:
    pass # similar stuff

I’d like to maintain some form of backward compatibility, and ClassB is essentially the same as ClassA so I was thinking I could either do:

ClassA = ClassB

# or

class ClassA(ClassB):
    pass

I’m not sure if there’s much of a difference in how those work really, although I guess the second implies an inheritance structure. The issue I’m having is with type hints. Since ClassA and ClassB are written in Rust, the only way to explicitly write type hints is through a __init__.pyi file. Now I have to write separate hints for ClassB and ClassC because they only work with the B or C variants of other classes, but I’m struggling with a way to write the hints for ClassA. Particularly, I could write identical stubs for As and Bs, and write union types for every time a method takes or returns one of these, but this would take a lot of time and result in a lot of duplicate code. Is there a way to avoid this?

Note that I am not looking for a type alias (as far as I know).

Edit: I gave up too quickly, I think I’ve answered my own question. I now only have type hints for B and C versions, and under the B type hint I just have the same ClassA = ClassB which I have in the __init__.py file (it has to be after the type hint because those files really are read top to bottom).

🌐
Towards Data Science
towardsdatascience.com › home › latest › python type hinting: from type aliases to type variables and new types
Python Type Hinting: From Type Aliases To Type Variables and New Types | Towards Data Science
January 22, 2025 - Simply put, with so complex types, raw type signatures will make static checkers happy – but they will unlikely make the users’ lives easier. Type aliases can help achieve that – they help communicate additional information about a variable, function, class or method to the user.
🌐
GitHub
github.com › python › typing › discussions › 1850
Mypy: how to use type aliases in generic classes · python/typing · Discussion #1850
For example, T_o_wo is bound to the scope of the type alias T_c_wo and also the class MyDecoCls. At runtime, T_o_wo is the same global object, but a type checker will treat these as completely independent type variables because they have different scopes. If you're using Python 3.12, you may want to switch to the new PEP 695 syntax for defining generics.
Author   python
🌐
Python.org
discuss.python.org › typing
Class-scoped `type` statement that references outer-scoped `TypeVar` - Typing - Discussions on Python.org
December 1, 2023 - Using traditional ways to define a type alias, it has been illegal for a class-scoped type alias definition to reference an outer-scoped TypeVar. This makes sense because these traditional type alias mechanisms implicitly bind type variables to their scope, so the use of an already-bound TypeVar is ambiguous. class A(Generic[T]): X1 = list[T] # pyright & mypy error: T is already bound X2: TypeAlias = list[T] # pyright & mypy error: T is already bound With the new type statement intro...
🌐
GitHub
github.com › python › typing › discussions › 1345
Type alias in generic class using bound type variable · python/typing · Discussion #1345
In essence, I don't understand why the type variable is not functionally equivalent to a concrete type within the class. As a workaround, you could define a generic type alias and then bind that generic type alias to the type variable.
Author   python
🌐
Austin
austin.ky › blog › python-typing-newtype
Consider Python’s NewType Instead of an Alias
Type systems are one of our better safeguards for this, and the typing module with mypy is the closest thing we have to this in Python right now. Alas, type systems are not a silver bullet, and it’s essential to understand their limitations. But these limitations shouldn’t stop us from leveraging them whenever we can. We can’t let perfection be the enemy of good. Next time you code Python and write out a type alias, ask yourself if the name you are aliasing is the same thing as the type you are aliasing it to.
🌐
Mypy
mypy.readthedocs.io › en › stable › generics.html
Generics - mypy 1.19.1 documentation
Example (Python 3.12 syntax): from example1 import AliasType from example2 import Vec # AliasType and Vec are type aliases (Vec as defined above) def fun() -> AliasType: ... type OIntVec = Vec[int] | None · Type aliases defined using the type statement are not valid as base classes, and they can’t be used to construct instances:
🌐
Python.org
discuss.python.org › python help
PEP 695 type aliases not suitable as replacement for typing.TypeAlias? - Page 2 - Python Help - Discussions on Python.org
January 18, 2024 - I would use explicit aliases and ... repeat the same type parameter over and over again inside a type expression. If I want a shorter name for a class I will use a regular assignment, because it’s not just a type alias, it’s an actual type....
🌐
Mimo
mimo.org › glossary › python › alias
Python Alias: Simplified Guide & Best Practices | Learn Now
from typing import Dict, List # Creating an alias for the complex type DataDict = Dict[str, List[int]] def process_data(data: DataDict) -> None: # Function implementation ... Become a Python developer. Master Python from basics to advanced topics, including data structures, functions, classes, and error handling
🌐
Reddit
reddit.com › r/learnpython › help understanding type aliases
r/learnpython on Reddit: Help understanding Type Aliases
April 28, 2025 -

Hi

Im reading through the typing documentation https://docs.python.org/3/library/typing.html and have a question that I cannot answer.

In the past when I wanted to use type aliases I would use code like Vector = list[float] (I think that I must have picked this up from a post on stack overflow or something).

However, in the document above it suggests using the code type Vector = list[float].

The difference between the two is that the data type is types.GenericAlias (the list[float]) for the first Vector and typing.TypeAliasType for the second Vector.

But besides that I am not really sure what is the difference between these two methods. Im not sure where the reason to use one over the other is. Im also not sure where the documntation is for the first example (maybe technically this is not a Type Alias).

Im not sure if anyone can help here?