Python Type Hints - Make Mypy disallow implicit optional types

Optional? ¯_(ツ)_/¯

Update (2022-11-08): Mypy 0.990 was just released, which enables the implicit optional type check by default.

The original type hint proposal, PEP 484, initially allowed implicit optional types in function signatures. That is, a parameter with a default value of None would have its type automatically interpreted as optional. For example, this signature:

def message(name: str = None) -> None:
    ...

…would be equivalent to allowing None in the type:

def message(name: str | None = None) -> None:
    ...

That would be written typing.Optional[str] with the old syntax.

Four years after its inception, a discussion lead to PEP 484 being changed to remove this feature. The Python precept “explicit is better than implicit” won out. The union types section of the PEP now ends:

A past version of this PEP allowed type checkers to assume an optional type when the default value is None

This is no longer the recommended behavior. Type checkers should move towards requiring the optional type to be made explicit.

So now that first example should produce a type checking error, and you need to write the second version, with an explicit | None in the type.

Althought this was a while ago in 2018, Mypy’s default configuration hasn’t caught up. As of version 0.982, Mypy still allows implicit optional types. But you can opt-in to disallowing them by enabling the no_implicit_optional option, for example in pyproject.toml:

[tool.mypy]
no_implicit_optional = true

Then, Mypy will report errors for every implicit optional type. If you then check that first example:

$ mypy example.py
example.py:1: error: Incompatible default for argument "name" (default has type "None", argument has type "str")
Found 1 error in 1 file (checked 1 source file)

The Mypy 0.981 release post announced turning this option on by default:

Implicit Optional Types Will Be Disabled by Default

A future mypy feature release (possibly the next one after 0.98x) will disable implicit optional types such as these by default, and they will have to be explicitly enabled…

It also promises to make migration easier:

We hope to provide a migration tool that will automatically switch implicit optional types to explicit ones in function signatures.

But if you are just starting out with type hints, or you have a relatively small project, I’d recommend enabling the option today. I do so on all my projects. Adding | None to a few parameters is not that much work to be up-to-date with the standards.

Fin

May your options always be explicit,

—Adam


Make your development more pleasant with Boost Your Django DX.


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: ,