Repository: TypeScript
Issue: Optional Generic Arguments in Tuple
Labels: Suggestion,Needs Proposal

## ⭐ Suggestion

Make support for optional generic arguments in tuple

```tsx
type OptionalTuple<A = void, B = void, C = void> = [A, B, C]

const test: OptionalTuple = [ 1 ]; // should be casted to OptionalTuple<number>
```

## 📃 Motivating Example

I have the next JS code. It will type `1, 2, 3` into Chrome Dev Tools console output

```tsx
const OptionalTuple = async ({ fetchState, children, }) => {
    const data = await Promise.all(await fetchState());
    return children(...data);
};

const App = () => {
    const fetchState = () => [
        Promise.resolve(1),
        Promise.resolve(2),
        Promise.resolve(3),
    ];
    return OptionalTuple({
        fetchState,
        children: console.log,
    });
};

App() // 1, 2, 3
```

I want to make It strictly typed **to enable IntelliSense in VSCode**. I tried, so I attach my last attempt below

```tsx
declare namespace JSX {
    export type Element = any;
}

interface IOptionalTupleProps<A = void, B = void, C = void> {
    fetchState: () => Promise<[A, B, C]> | [A, B, C];
    children: (...data: [A, B, C]) => JSX.Element;
};

const OptionalTuple = async ({
    fetchState,
    children,
}: IOptionalTupleProps) => {
    const data = await Promise.all(await fetchState());
    return children(...data);
}

const App = () => {

    const fetchState = () => [
        Promise.resolve(1),
        Promise.resolve(2),
        Promise.resolve(3),
    ] as const;

    return OptionalTuple({
        fetchState,
//      ^^^^^^^^^^
//      The type 'readonly [Promise<number>, Promise<number>, Promise<number>]' is 'readonly' and cannot be assigned to the mutable type '[void, void, void]'    
        children: console.log,
    });
}

App();
```

But for now I am getting the following error. It looks like `readonly [Promise<number>]` can't be casted to `[Promise<number>, void, void]`

```
The type 'readonly [Promise<number>, Promise<number>, Promise<number>]' is 'readonly' and cannot be assigned to the mutable type '[void, void, void]'.
```

## 💻 Use Cases

Optional tuple arguments can be used [in React higher-order-components](https://reactjs.org/docs/higher-order-components.html) to enable powered type checking in functional programming

## 🔍 Search Terms

 - `cannot be assigned to the mutable type '[void, void, void]'`
 - `type '[Promise<number>]' cannot be assigned to '[Promise<number>, void, void]'`
 - `readonly  cannot be assigned`
 - `Argument of type '[]' is not assignable to parameter of type`
 - `optional generic rest parameters union not callable`

## ✅ Viability Checklist

My suggestion meets these guidelines:

* [x] 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).