Repository: TypeScript
Issue: Allow spreading `Parameters<T>` into a named tuple
Labels: Suggestion,In Discussion

# Suggestion

Allow spreading named tuples into named tuples, and make `Parameters<T>` a named tuple.

## 🔍 Search Terms

parameters named tuple

## ✅ Viability Checklist

My suggestion meets these guidelines:

* [ ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).

Not expert enough with Typescript to know whether this would be a breaking change. Definitely wouldn't break any JavaScript code, but might "break" some existing usage of the `Parameters<T>` utility? Breaking could be avoided if there was some sort of logic of "if spreading this named tuple into another named tuple, keep the names, but if spreading it into an unnamed tuple, drop the names", maybe?

## ⭐ Suggestion

Say I have this function:
```ts
type ClampFn = (value: number, range: [min: number, max: number]) => number;
```
Now I want to create a named tuple, which includes all its parameters, _and_ its return type at the end. Doing it manullay works of course:
```ts
type ManualType = [value: number, range: [min: number, max: number], returns: number]
```
But doing it via the `Parameters<T>` and `ReturnType<T>` utilities gives the error that "Tuple members must all have names or all not have names":
```ts
type InferredType = [...Parameters<ClampFn>, returns: ReturnType<ClampFn>];
                     ^^^^^^^^^^^^^^^^^^^^^^
```

Would be great if `Parameters<T>` returned a named tuple, and if it was possible to spread named tuples into named tuples and keeping the names (maybe already possible?). To prevent breaking, it should also be possible to spread a named tuple into an unnamed tuple (maybe already possible?).

https://www.typescriptlang.org/play?ts=4.7.2#code/C4TwDgpgBAwgNgQwLZgGIDsoF4oAoBuCcArhAFxTrFIBGEATgDRT0LoDm5UA2kgJboKVWg2ZIEADyHU69ALoBKbAD5KMhgG4AUFtCQoAWTbEiAFXDQc3QiS7DZzVhy68B0kUyjipaj3McQwMT06ADO7rJyuhZQAJLoAGYM9BAAJub6VgB0OQAKCKxIgQyhADzwyGjoygFBIeFQAEqBwegZEOWIKBjKctpAA

## 📃 Motivating Example

I've started using the [`test.each`](https://jestjs.io/docs/api#testeachtablename-fn-timeout) feature of Jest, and this would be very handy when defining the type of test-cases you expect to pass into the `each` function.

Currently have to do it manually, to get named parameters and auto-complete in the test-function parameter list:
```ts
    it.each<[input: number, range: [min: number, max: number], result: number]>(
      [
        [0, [1, 3], 1],
        [1, [1, 3], 1],
        [2, [1, 3], 2],
        [3, [1, 3], 3],
        [4, [1, 3], 3],
      ]
    )('%p clamped within %p should be %p', (input, range, result) => {
      expect(clamp(input, range)).toBe(result);
    });
```

## 💻 Use Cases

If I could spread `Parameters<T>` into a named tuple, then I could easily "lock" the type of test-cases with the actual function arguments, _and_ get correct parameter names in the named tuple directly from the function:

```ts
    it.each<[...Parameters<typeof clamp>, result: ReturnType<typeof clamp>]>(
      [
        [0, [1, 3], 1],
        [1, [1, 3], 1],
        [2, [1, 3], 2],
        [3, [1, 3], 3],
        [4, [1, 3], 3],
      ]
    )('%p clamped within %p should be %p', (input, range, result) => {
      expect(clamp(input, range)).toBe(result);
    });
```