Better type signature for `random`'s `sample()`
- Dominant language
- TypeScript
- Stars
- 3.6k
- Forks
- 681
- PR merge metrics
- No merged PRs in 30d
Description
**Is your feature request related to a problem? Please describe.**
Currently, the type signature for `sample()` is correct, but often overly broad, as it always includes `undefined`:
```ts
// type is number | undefined, even though we know it can only be 1, 2, or 3 (never undefined)
sample([1, 2, 3])
```
**Describe the solution you'd like**
`sample()` to narrow the type to exclude `undefined` in cases where TS can determine it statically.
The current signature is roughly this:
```ts
declare function sample(array: ArrayLike): T | undefined
```
A signature something like the following would be an improvement:
```ts
declare function sampleNext>(array: T):
T extends { 0: unknown }
? T[keyof T & number]
: T[keyof T & number] | undefined
```
[TS Playground](https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwGcoBbABwhAGFkY5UMAeAFQD4AKAKHnlhigE8AXPACCtAQBksAaxDMWAGg4BKYU3gAfeGlCIsqEMA4dQkWAhTpseQiXIgAciAAejMHgIZ46lxhCpgAlFxfilZBjRpVBwAd1QWdl4BNVUubm94X39A+ABveAAGYUjouPgAXzT09IB+bwBtWX4cRAyAMnhUZGIAIxAYAF0q6vg1RpBm1vUOrt7+gc1tAJA9AyMOd1RPHhCiwgwYfQBzeoWAXnhTjY8vJP4ARngL+oByKBeFeBeel6HN7buACYnpc3h8vj8FlAgv8MNctrcQgBmYT1TyHVBHT4AOlx6OOp3OoPen2+v3hAJCABZhPk9vjMZ8KJiMAALYSzPowCog14kiHk2E7PihGQIC504T3Jn+I5sqUVCmIkVhEDAiWFKUylns+CPco8GE3JXwHpQYBiFVikGSvXauW6go86HwWHGDgAblywyFRDIFBBfvs1Fo-jhPpuwoEBQAynYKMVlqtDIH4yA2HcCspDUtdPpDBGEVGHnH-SBhAyjqmyxmQvdsy7K4XKSLAaX7MIwYsydX7LXW8pm8qBEj2wn9hiqxcgxR+yPB9UhXcqWPyxPjr3Z8uF+klyFVauOd0uZv03dVTvuHurbI22mFdO03PRbfL67I2aLfuxYfcyt88Ap5sJ+lqSGKDZBDo-5rEO8AQFgfh8BACpaMCWhIkB9TSvAgKfEiAxvkK8GIVAEAiAQlA3A+tg1lhUJGgihGRsR-SkQAomQGBCH+yaAY+tEEcYi6RrwFYHASRJXNUWCtGwACyUBstifABDgxBsNmLDwNiACsDa0NipDIAQrJsC8zj8AAXi8TFFjAaDYMQIByVgRyshgABCIAcaQXFiZOixQbxQG8IOlSet6wlFjO4o0fYTiuEJu4ibsv5BQBIW7BBPEAbBdz3L+laZSK9Y5k2UUtgId5lp27zdj8xVVbZlX8KO97rpijWtc1w78Cu7VFfxfbbnl36yL+nL9F1F6jTeaq-o8Q1bmNao9aa5qgS+IBpUmGVLemIErdl6UwRVXgsUhKE4YsGH7WwWGfLh8D4WtF2keRlEItRMX3fc9HvoxsFvRAPl+TlayYYJs3+RJvJDNJskKUpKnAGpGnwFpun6TAhnGaZ5lWTZsH2fQWBOS5bmed5nHcUVWgnSmd2hRwlRAA)
**Describe alternatives you've considered**
The only case I can think of where this would lead to runtime types diverging from TS types is where the argument is statically detected to be an array-like with a `0` property but also having a spoofed `length` of `0`, e.g. `{ 0: 'xyz', length: 0 }`.
If that can't be fixed through further refinements of the type signature, it could be solved either by:
* Checking type of `length` is not `0` (but that still wouldn't detect where type is `{ 0: string, length: number }` but length is 0 at runtime)
* Throwing at runtime on such inputs
* Simply assuming they won't occur in real-world scenarios (a reasonable assumption, and if they _do_ occur it's likely to be due to a deeper underlying bug).
Contributor guide
Assessment
This issue has not been assessed yet.