The former is correct, if arg accepts an instance of CustomClass:

pythonCopydef FuncA(arg: CustomClass):
    #     ^ instance of CustomClass

In case you want the class CustomClass itself (or a subtype), then you should write:

pythonCopyfrom typing import Type  # you have to import Type

def FuncA(arg: Type[CustomClass]):
    #     ^ CustomClass (class object) itself

Like it is written in the documentation about Typing:

pythonCopyclass typing.Type(Generic[CT_co])

A variable annotated with C may accept a value of type C. In contrast, a variable annotated with Type[C] may accept values that are classes themselves - specifically, it will accept the class object of C.

The documentation includes an example with the int class:

pythonCopya = 3         # Has type 'int'
b = int       # Has type 'Type[int]'
c = type(a)   # Also has type 'Type[int]'

Update 2024: Type is now deprecated in favour of type

Answer from willeM_ Van Onsem on Stack Overflow
Top answer
1 of 2
287

The former is correct, if arg accepts an instance of CustomClass:

pythonCopydef FuncA(arg: CustomClass):
    #     ^ instance of CustomClass

In case you want the class CustomClass itself (or a subtype), then you should write:

pythonCopyfrom typing import Type  # you have to import Type

def FuncA(arg: Type[CustomClass]):
    #     ^ CustomClass (class object) itself

Like it is written in the documentation about Typing:

pythonCopyclass typing.Type(Generic[CT_co])

A variable annotated with C may accept a value of type C. In contrast, a variable annotated with Type[C] may accept values that are classes themselves - specifically, it will accept the class object of C.

The documentation includes an example with the int class:

pythonCopya = 3         # Has type 'int'
b = int       # Has type 'Type[int]'
c = type(a)   # Also has type 'Type[int]'

Update 2024: Type is now deprecated in favour of type

2 of 2
41

Willem Van Onsem's answer is of course correct, but I'd like to offer a small update. In PEP 585, type hinting generics were introduced in standard collections. For example, whereas we previously had to say e.g.

pythonCopyfrom typing import Dict

foo: Dict[str, str] = { "bar": "baz" }

we can now forgo the parallel type hierarchy in the typing module and simply say

pythonCopyfoo: dict[str, str] = { "bar": "baz" }

This feature is available in python 3.9+, and also in 3.7+ if using from __future__ import annotations.

In terms of this specific question, it means that instead of from typing import Type, we can now simply annotate classes using the built-in type:

pythonCopydef FuncA(arg: type[CustomClass]):
🌐
Reddit
reddit.com › r/learnpython › type-hinting with user defined classes
r/learnpython on Reddit: Type-hinting with user defined classes
November 14, 2023 -

I have two custom classes, one of which requires the other as an input argument.

class Authentication(object):
    def __init__(self) -> None:
        self.auth_data = self._resolve_auth()

class Data(object):
    def __init__(self, authentication) -> None:
        self.baseurl = authentication.baseurl
        self.token = authentication.token

I have the Authentication class defined in a seperate file in my project. So my question is, if I want to apply type-hinting to the Data class i.e.

def __init__(self, authentication: Authentication) -> None:

How do I go about doing this without having to import the Authentication class into my file which contains the Data class? It seems like overkill just to get proper type-hinting.

🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
User-defined generics for parameter expressions are also supported via parameter specification variables in the form [**P]. The behavior is consistent with type variables’ described above as parameter specification variables are treated by the typing module as a specialized type variable. The one exception to this is that a list of types can be used to substitute a ParamSpec: >>> class Z[T, **P]: ...
🌐
DataCamp
campus.datacamp.com › courses › intermediate-object-oriented-programming-in-python › custom-class-features-and-type-hints
Type hinting with custom classes | Python
In this exercise, you'll use built-in type keywords, the typing library, and your own custom class to practice type hinting. List has been imported from the typing library.
🌐
Mypy
mypy.readthedocs.io › en › stable › cheat_sheet_py3.html
Type hints cheat sheet - mypy 1.19.1 documentation
It's only for mypy -- there's no runtime check. a = [4] b = cast(list[int], a) # Passes fine c = cast(list[str], a) # Passes fine despite being a lie (no runtime check) reveal_type(c) # Revealed type is "builtins.list[builtins.str]" print(c) # Still prints [4] ... the object is not changed or casted at runtime # Use "TYPE_CHECKING" if you want to have code that mypy can see but will not # be executed at runtime (or to have code that mypy can't see) if TYPE_CHECKING: import json else: import orjson as json # mypy is unaware of this · In some cases type annotations can cause issues at runtime,
🌐
Adam Johnson
adamj.eu › tech › 2021 › 05 › 16 › python-type-hints-return-class-not-instance
Python type hints: specify a class rather than an instance thereof - Adam Johnson
Mypy 0.800+ supports this new syntax on older Python versions if you use from __future__ import annotations. ... from typing import Type ... def make_animal(animal_class: Type[Animal], name: str) -> Animal: return animal_class(name=name)
🌐
Python
peps.python.org › pep-0484
PEP 484 – Type Hints | peps.python.org
It is allowable to use string literals as part of a type hint, for example: class Tree: ... def leaves(self) -> List['Tree']: ...
🌐
Dagster
dagster.io › blog › python-type-hinting
Using Type Hinting in Python Projects
For example, if a variable can be either a str or an int, you can provide a type hint like this: from typing import Union def process(data: Union[str, int]) -> None: # This function can handle either a string or an integer · In newer versions of Python, you can use the pipe (|) operator to indicate a type that can be one of several options, replacing the need for Union: def process(data: str | int) -> None: # This function can handle either a string or an integer · The Any class is used to indicate that a variable can be of any type.
Find elsewhere
🌐
FastAPI
fastapi.tiangolo.com › python-types
Python Types Intro - FastAPI
Python has support for optional "type hints" (also called "type annotations"). These "type hints" or annotations are a special syntax that allow declaring the type of a variable.
🌐
Sololearn
sololearn.com › en › Discuss › 1932387 › in-python3-type-hinting-how-do-you-type-hint-a-custom-type-class-or-object
In python3 type-hinting, how do you type-hint a custom type class or object? | Sololearn: Learn to code for FREE!
My question is about the new feature in python 3 that allows type hints like in Typescript.. My desired outcome is to hint a function/variable/return-type, to a custom class i made or its object..
🌐
FastAPI Tutorial
fastapitutorial.com › blog › advanced-type-hints
2. Advanced Type Hints
3. Custom Types: If your type hints are becoming too lengthy, then it becomes very difficult to read and understand the function. In such cases, we can extract the type annotation and build our own custom type. Let's see an example of this. from typing import List Image = List[List[int]] def flatten_image(image: Image)->List: #custom type Image flat_list = [] for sublist in image: for item in sublist: flat_list.append(item) return flat_list image = [[1,2,3],[4,5,6]]
🌐
Readthedocs
python-type-checking.readthedocs.io › en › latest › types.html
Type Classes — Guide to Python Type Checking 1.0 documentation
This is admittedly a bit of a nuisance, but it makes more sense when you consider that the syntax integration in python 3.5 means you’re attaching objects to function definitions just as you do when providing a default value to an argument. In fact, you can use typing.get_type_hints() function to ...
🌐
Python Like You Mean It
pythonlikeyoumeanit.com › Module5_OddsAndEnds › Writing_Good_Code.html
Writing Good Code — Python Like You Mean It
We will define our own Dog class, and will write a function that expects the Dog class-object itself (type-hinted as Type[Dog]). The function will create several instances of the Dog class (type-hinted simply as Dog), and will return them in a list. # type-hinting a custom class from typing import List, Type class Dog: def __init__(self, name): self.name = name # cls is expected to be the class-object, `Dog`, itself # This function returns a list of instances of the `Dog` type def list_famous_dogs(cls: Type[Dog]) -> List[Dog]: return [cls(name) for name in ["Lassie", "Shadow", "Air Bud"]]
🌐
JetBrains
jetbrains.com › help › pycharm › type-hinting-in-product.html
Type hinting in PyCharm | PyCharm Documentation
Typeshed is a set of files with type annotations for the standard Python library and various packages. Typeshed stubs provide definitions for Python classes, functions, and modules defined with type hints. PyCharm uses this information for better code completion, inspections, and other code insight features. PyCharm comes bundled with Typeshed stubs. The list of available Typeshed stubs is shown in the project view under the node External Libraries | <Python interpreter> | Typeshed Stubs.
🌐
InfoWorld
infoworld.com › home › software development › programming languages › python
Get started with Python type hints | InfoWorld
June 18, 2025 - If you need an explicit self hint for the class that refers to whatever class is in context, and you’re using Python 3.11 or later, you can import Self from the typing module and use that as a hint. When using type hints for custom objects, we sometimes need to provide a type hint for an object that hasn’t yet been defined.
Top answer
1 of 5
346

As of May 2015, PEP 484 (Type Hints) has been formally accepted. The draft implementation is also available at github under ambv/typehinting.

In September 2015, Python 3.5 was released with support for Type Hints and includes a new typing module. This allows for the specification of types contained within collections. As of November 2015, JetBrains PyCharm 5.0 fully supports Python 3.5 to include Type Hints as illustrated below.

from typing import List

def do_something(l: List[str]):
    for s in l:
        s  # str

Original Answer

As of Aug 2014, I have confirmed that it is not possible to use Python 3 type annotations to specify types within collections (ex: a list of strings).

The use of formatted docstrings such as reStructuredText or Sphinx are viable alternatives and supported by various IDEs.

It also appears that Guido is mulling over the idea of extending type annotations in the spirit of mypy: http://mail.python.org/pipermail/python-ideas/2014-August/028618.html

2 of 5
228

As of Python 3.9, builtin types are generic with respect to type annotations (see PEP 585). This allows to directly specify the type of elements:

def my_func(l: list[int]):
    pass

This also extends to most other container types of the standard library, for example collections.deque or collections.abc.Mapping.


Various tools may support this syntax earlier than Python 3.9. When annotations are not inspected at runtime, the syntax is valid using quoting or __future__.annotations.

# quoted
def my_func(l: 'list[int]'):
    pass
# postponed evaluation of annotation
from __future__ import annotations

def my_func(l: list[int]):
    pass

As a consequence of PEP 585, most helpers in typing corresponding to standard library types are deprecated, such as typing.List, typing.Deque or typing.Mapping. They should only be used if compatibility with Python versions prior to 3.9 is required.

🌐
DataCamp
campus.datacamp.com › courses › intermediate-object-oriented-programming-in-python › custom-class-features-and-type-hints
Type Hints | Python
To hint this, we've used the List class from the typing library and the str keyword with the syntax List-str. Using the Dict class, we can hint that the student_gpas dictionary is made up of string keys and float values using the syntax Dict-str-float.