diff -r da9898e7e90d -r c5151efd2bca Doc/library/typing.rst --- a/Doc/library/typing.rst Wed Jul 27 16:59:22 2016 +0200 +++ b/Doc/library/typing.rst Thu Jul 28 10:12:22 2016 -0700 @@ -29,10 +29,77 @@ Type aliases ------------ -A type alias is defined by assigning the type to the alias:: +A type alias is defined by assigning the type to the alias. In this example, +``Vector`` and ``List[float]`` will be treated as interchangeable synonyms:: + from typing import List Vector = List[float] +Type aliases are useful for simplifying complex type signatures. For example:: + + from typing import Dict, Tuple, List + + + ConnectionOptions = Dict[str, str] + Address = Tuple[str, int] + Server = Tuple[Address, ConnectionOptions] + + def broadcast_message(message: str, servers: List[Server]) -> None: + ... + + # The static type checker will treat the previous type signature as + # being exactly equivalent to this one. + def broadcast_message(message: str, servers: List[Tuple[Tuple[str, int], Dict[str, str]]]) -> None: + ... + +NewType +------- + +Use the ``NewType`` helper function to create distinct types:: + + from typing import NewType + + UserId = NewType('UserId', int) + some_id = UserId(524313) + +The static type checker will treat the new type almost as if it were a subclass +of the original type. This is useful in helping catch logical errors:: + + def get_user_name(user_id: UserId) -> str: + ... + + user_a = get_user_name(UserId(42351)) # typechecks + user_b = get_user_name(-1) # does not typecheck; an int is not a UserId + +You may still perform all ``int`` operations on a variable of type ``UserId``, but the +result will always be of type ``int``. This lets you pass in a ``UserId`` wherever an +``int`` might be expected, but will prevent you from accidentally creating a ``UserId`` +in an invalid way:: + + output = UserId(23413) + UserId(54341) # `output` is of type `int`, not `UserId` + +Note that these checks are enforced only by the static type checker. At runtime the statement +``Derived = NewType('Derived', Base)`` will make ``Derived`` a function that immediately +returns whatever parameter you pass it. That means the expression ``Derived(some_value)`` +does not create a new class or introduce any overhead beyond that of a regular function call. + +More precisely, the expression ``some_value == Derived(some_value)`` is always true at runtime. + +See :pep:`484` for more details. + +.. note:: + + Recall that type aliases declares two types to be *equivalent* to one another. + Doing ``Alias = Original`` will make the static type checker treat ``Alias`` as being + *exactly equivalent* to ``Original`` in all cases. This is useful when you want to simplify + complex type signatures. + + In contrast, ``NewType`` declares one type to be a *derivative* of another. + Doing ``Derived = NewType('Derived', Original)`` will make the static type checker + treat ``Derived`` as a *subclass* of ``Original``, which means a value of type + ``Original`` cannot be used in places where a value of type ``Derived`` is expected. + This is useful when you want to prevent logic errors with minimal runtime cost. + Callable --------