Make type aliases show up in help()

When quickly checking why one thing or another is breaking on a remote machine, I often end up in a repl where I use help() to look at whatever seems to cause an issue. Naturally, a common problem that the wrong thing gets passed into another thing, and so it is very useful to see type annotations in help(). Unfortunately, quite often those end up being useless, because help() cannot un-resolve type aliases.

For reference, take this function definition:

>>> from numpy.typing import NDArray, ArrayLike
>>> def square(x: ArrayLike) -> NDArray:
...     return np.square(x)

and its help() output:

square(x: Union[numpy.__array_like._SupportsArray[numpy.dtype], numpy.__nested_sequence._NestedSequence[numpy.__array_like._SupportsArray[numpy.dtype]], bool, int, float, complex, str, bytes, numpy.__nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]]) -> numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]

That’s of course because ArrayLike is a complicated beast, and what makes it into the function signature is its value, not its name.

It would therefore have been nice if PEP 613 had given us an optional construct like this:

ArrayLike = TypeAlias('ArrayLike', ...)

so that help() and such could display more meaningful type aliases.

4 Likes

I don’t know if that’s the best solution, but I agree that it would be really nice to have access to the type aliases rather than their decomposition.

Would you try from __future__ import annotations?

Sure, but isn’t that effectively the same as manually typing the following?

>>> def square(x: 'ArrayLike') -> 'NDArray':
...     return np.square(x)

That fixes the symptom, but the issue is that we do not have explicit, unevaluated type aliases. (Mea culpa, my title and example could have been better to convey what idea I am talking about.)

1 Like

Is it possible to make the compond types classes, or class instances?
I don’t know enough about the typing stuff to answer that question.

But if, say, ArrayLike were not its current compound thing but a class
(or class instance) with the right semantics we’d get there. (Along with
a way to easily do that for other things of our own making.) Maybe that
breaks the ability of type checkers to compute stuff, I don’t know.

Cheers,
Cameron Simpson cs@cskk.id.au