3

As this great answer suggests, from Python 3.7 onward it's possible to use forward declarations in type annotations if the

from __future__ import annotations

instruction is used.

However, this still doesn't work if I want to create an alias for the annotation type:

from __future__ import annotations
import typing

MyType1 = typing.Union[str, MyType2]
MyType2 = typing.Mapping[str, MyType1]

This still gives me NameError: name 'MyType2' is not defined

I know about the fallback syntax using string literals, and it does work. However, I'm curious whether it's somehow possible to use the formally available new approach.

Community
  • 1
  • 1
Semisonic
  • 1,152
  • 8
  • 21

1 Answers1

3

One technique is to use the typing.TYPE_CHECKING constant. This constant is always false at runtime, but is treated as if it were always true by type checkers such as mypy:

from __future__ import annotations
from typing import TYPE_CHECKING, Union, Mapping
if TYPE_CHECKING:
    MyType1 = Union[str, MyType2]
    MyType2 = Mapping[str, MyType1]

Since this constant is False at runtime, Python will never try evaluating either type alias, which lets you dodge the NameError.

You'll need to either use the from __future__ import annotations directive or use string literal types whenever you use either type hint though, of course.

Michael0x2a
  • 58,192
  • 30
  • 175
  • 224