I never really understood the importance of `Optional`. Often it can be left out altogether and in other cases I find `Union[T, None]` more expressive (explicit) than `Optional[T]` (+ the latter saves only 3 chars). Especially for people not familiar with typing, the meaning of `Optional` is not obvious at first sight. `Union[T, None]` on the other hand is pretty clear. Also in other cases, where the default (fallback) is different from `None`, you'd have to use `Union` anyway. For example a function that normally returns an object of type `T` but in some circumstances it cannot and then it returns the reason as a `str`, i.e. `-> Union[T, str]`; `Optional` won't help here. Scanning through the docs and PEP I can't find strongly motivating examples for `Optional` (over `Union[T, None]`). E.g. in the following: def lookup(self, name: str) -> Optional[Node]: nodes = self.get(name) if nodes: return nodes[-1] return None I would rather write `Union[Node, None]` because that's much more explicit about what happens. Then introducing `~T` in place of `Optional[T]` just further obfuscates the meaning of the code: def lookup(self, name: str) -> ~Node: The `~` is easy to be missed (at least by human readers) and the meaning not obvious. For `Union` on the other hand it would be more helpful to have a shorter syntax, `int | str` seems pretty clear, but what prevents tuples `(int, str)` from being interpreted as unions by type checkers. This doesn't require any changes to the built-in types and it is aligned with the already existing syntax for checking multiple types with `isinstance` or `issubclass`: `isinstance(x, (int, str))`. Having used this a couple of times, whenever I see a tuple of types I immediately think of them as `or` options.