Type Hints in Python. Why and How?

One of the main characteristics of Python is that it is a dynamic typed language. This means that the type of the variables is checked at runtime, allowing a simple syntax as below, with no type declaration.

This can be very handy sometimes, but it can cause a lot of trouble too. The main benefits when writing is the simplicity, with the code being less verbose than languages such as C/C++ and Java and no need to static_casts or similar functions.

But in the other hand, when the code becomes more complex and bigger or when you’re introduced to a new project, you come a long way guessing some variables types and what is happening in each function. Some common questions are: is this a list? an object? or a dictionary?; does this function return a number? or a string?; should I pass a list or a dictionary to this function?. Then you have to print that variable and see that it may be a string, a list of numbers or simply None.

Another problem is IntelliSense. One of the main benefits when using an IDE is having the autocompletion or suggestion for a function or class method. This saves a lot of time and prevents many Google searches to know the syntax for replace string method. But, since the variables types are known only at runtime, the autocomplete lack some methods and also can’t say when you’re trying to sum an object with a dictionary, this is not supported.

TypeScript and PEP 484

A language that have some similar problems is JavaScript, a dynamic typed language as well mainly used for web development. TypeScript was created to be “typed JavaScript at any scale”, solving that problem. It is a superset of JS that is becoming more and more popular over the years. Its main feature is to optionally add data type to variables and functions.

In Python, since version 3.5, PEP 484 introduced Type Hints, a way to say statically the variables types. In the example below, list_numbers is annotated (type hinted) as a list of integers (List[int]) and my_str as a string (str). It’s important to stress that it works in very different way than TypeScript, but achieves similar goals.

The main focus of the PEP is to tell linters what the expected types are, but it does not change runtime behavior. This means that, even if a variable is annotated as string, it can be assigned in runtime as an integer, demonstrated by the example below.

But this doesn’t mean that the annotations are useless. Keeping the runtime behavior is important to not break compatibility and to not add an runtime overhead for checking every variable type in the program against its annotation.

The main feature of PEP 484 is for linters, IntelliSense and statically checking for code errors. These may be a lot of fancy words, but it basically says that: your IDE now knows a lot more about your code and can help you more. To make use of these features, the main linter used for that is mypy. You can check here to configure its use with VS Code.

Trust me, you will thank later to start using type hints. For bigger or older projects, it becomes a lot easier to debug and check how your code works or what is wrong with it. If you made the transition from JavaScript to TypeScript, you already know the benefits.


There are libraries that already take advantage of these features

  • FastAPI creates a REST API with type checking for parameters and automatically serves its documentation
  • Pydantic allows the creation of models with given keys, its type and can generate a JSON schema

You can save a lot of time and headache by start using type hints for bigger projects. There are a lot of things you can automate as well, as FastAPI shows.

An example is provides below. To know more about Type Hints you can check Python documentation on it.

Python developer and a great fan of podcasts. Email: waine.oliveira.jr@gmail.com. Site: wainejr.com