Consider the following function:

```
import numpy as np
def law_of_cosines(side1, side2, angle):
return np.sqrt(
np.square(side1) +
np.square(side2) -
2 * side1 * side2 * np.cos(angle)
)
```

This function can accept more or less arbitrary combinations of Numpy arrays of `float`

-based dtypes, “array-like” objects (sequences, objects implementing certain magic methods) containing either Numpy float objects or native Python `float`

s, or individual “scalar” Numpy float objects or native Python `float`

instances.

This topic has been discussed at least once before:

However my goal *is* to be at least somewhat pedantic. I want to accept a reasonably broad range of input types, while *also* being strict about dtypes. For example, the proposed solution in the thread above would not prevent me from passing `['a', 'b', 'c']`

into my `law_of_cosines`

function, and I would definitely like to prevent that.

I can do pretty well by assuming that inputs are *only* `float`

or `NDArray[np.floating[Any]]`

, but that leaves out `ArrayLike`

entirely, which is not parameterizable. Thus my function will accept `3.5`

and `np.asarray([3.5])`

but not `[3.5]`

, which seems unfortunate.

What is the currently recommended best practice for typing Numpy functions that are meant to be “forgiving” about their input types? Or is this still a WIP topic?