Repository: numpy/numpy
File: numpy/_core/fromnumeric.pyi (Python)

Code before:
    "ravel",
    "repeat",
    "reshape",
    "resize",
    "round",
    "searchsorted",
    "shape",
    "size",
    "sort",
    "squeeze",
    "std",
    "sum",
    "swapaxes",
    "take",
    "trace",
    "transpose",
    "var",
]

_ScalarT = TypeVar("_ScalarT", bound=generic)
_NumberOrObjectT = TypeVar("_NumberOrObjectT", bound=np.number | np.object_)
_ArrayT = TypeVar("_ArrayT", bound=np.ndarray[Any, Any])
_ShapeT = TypeVar("_ShapeT", bound=tuple[int, ...])
_ShapeT_co = TypeVar("_ShapeT_co", bound=tuple[int, ...], covariant=True)
_IndexArray = NDArray[np.signedinteger] | NDArray[np.unsignedinteger] | NDArray[np.bool_] # type alias for argmin / argmax
_OutT = TypeVar("_OutT", bound=_IndexArray) # Type variable, must be assignable to _IndexArray

@type_check_only
class _SupportsShape(Protocol[_ShapeT_co]):
    # NOTE: it matters that `self` is positional only
    @property
    def shape(self, /) -> _ShapeT_co: ...

# a "sequence" that isn't a string, bytes, bytearray, or memoryview
_T = TypeVar("_T")
_PyArray: TypeAlias = list[_T] | tuple[_T, ...]
# `int` also covers `bool`
_PyScalar: TypeAlias = complex | bytes | str

@overload
def take(
    a: _ArrayLike[_ScalarT],
    indices: _IntLike_co,
    axis: None = ...,
    out: None = ...,
    mode: _ModeKind = ...,
) -> _ScalarT: ...
@overload
def take(
    a: ArrayLike,
    indices: _IntLike_co,

Review comment (suggestion):
Since `_IndexArray` is only used once, it would be a bit cleaner to inline it. It's also fine if you want to keep it, but in that case it should then be annotated as `TypeAlias`.

Also, `_IndexArray` is currently too restrictive, because it would currently reject valid types like like `NDArray[bool_ | int_]`, `NDArray[int8 | uint8]`, and `NDArray[integer]`.

Additionally, it could help to have the name of the type parameter reflect the restriction on its upper bound. The name shows up in case of type-checker errors, e.g. when someone passes `NDArray[np.float64]`. And if the user then sees `_OutT`, it won't be very informative.

So given that, I'd personally probably go for something like:

```suggestion
_BoolOrIntArrayT = TypeVar("_BoolOrIntArrayT", bound=NDArray[np.integer | np.bool])
```

But there are probably many other good options too 🤷🏻 

Code after:
    "ravel",
    "repeat",
    "reshape",
    "resize",
    "round",
    "searchsorted",
    "shape",
    "size",
    "sort",
    "squeeze",
    "std",
    "sum",
    "swapaxes",
    "take",
    "trace",
    "transpose",
    "var",
]

_ScalarT = TypeVar("_ScalarT", bound=generic)
_NumberOrObjectT = TypeVar("_NumberOrObjectT", bound=np.number | np.object_)
_ArrayT = TypeVar("_ArrayT", bound=np.ndarray[Any, Any])
_ShapeT = TypeVar("_ShapeT", bound=tuple[int, ...])
_ShapeT_co = TypeVar("_ShapeT_co", bound=tuple[int, ...], covariant=True)
_BoolOrIntArrayT = TypeVar("_BoolOrIntArrayT", bound=NDArray[np.integer | np.bool])

@type_check_only
class _SupportsShape(Protocol[_ShapeT_co]):
    # NOTE: it matters that `self` is positional only
    @property
    def shape(self, /) -> _ShapeT_co: ...

# a "sequence" that isn't a string, bytes, bytearray, or memoryview
_T = TypeVar("_T")
_PyArray: TypeAlias = list[_T] | tuple[_T, ...]
# `int` also covers `bool`
_PyScalar: TypeAlias = complex | bytes | str

@overload
def take(
    a: _ArrayLike[_ScalarT],
    indices: _IntLike_co,
    axis: None = ...,
    out: None = ...,
    mode: _ModeKind = ...,
) -> _ScalarT: ...
@overload
def take(
    a: ArrayLike,
    indices: _IntLike_co,
    axis: SupportsIndex | None = ...,