PERF: avoid creating numpy array in groupby.first|last
A unneeded numpy array is created for each group when calling ``groupby.first`` and ``groupby.last`` on ExtensionArrays. This avoids that.

```python
>>> cat = pd.Categorical(["a"] * 1_000_000 + ["b"] * 1_000_000)
>>> ser = pd.Series(cat)
>>> %timeit ser.groupby(cat).first()
210 ms ± 3.03 ms per loop  # master
78.4 ms ± 766 µs per loop  # this PR
```

The same speedup is archieved for ``groupby.last``. The above is 3x faster than in master because there are two groups == we save creating two arrays. If there were more groups/larger arrays, we'd get even more improvements.

Also adds some type hints to help understand what parameters these funtions accept.
thanks @topper-123 very nice