Skip to content

Allow inferring rest element types in conditional types involving tuples #25719

@AlCalzone

Description

@AlCalzone

Search Terms

rest element infer tuple

Suggestion

Currently, inferring single elements of tuple types is possible using the infer keyword:

type FirstArg<T extends any[]> = 
	T extends [infer R, ...any[]] ? R : 
	T extends [] ? undefined : 
	never;
type T1 = FirstArg<[number, 2, 3]>; // number
type T2 = FirstArg<[1, 2, 3]>; // 1
type T3 = FirstArg<["", 2]>; // ""
type T4 = FirstArg<[]>; // undefined

However it is not possible to infer the type of the remaining arguments in one go, except by resorting to functions:

type RestArgs<T extends any[]> = 
	T extends [any, infer R[]] ? R : // this does not work - no way to specify that R should be an array!
	T extends [any] ? []] : 
	never;

// this does
type RestArgs<T extends any[]> =
	((...args: T) => void) extends ((first: any, ...rest: infer S1) => void) ? S1
	: T extends [infer S2] ? []
	: T extends [] ? []
	: never;
type T1 = RestArgs<[1,2,3]>; // [2, 3]
type T2 = RestArgs<[1,2]>; // [2]
type T3 = RestArgs<[1]>; // []
type T4 = RestArgs<[]>; // []

I would like to see the possibility to infer rest types in tuples, e.g. like this (square brackets):

type RestArgs<T extends any[]> = T extends [any, infer R[]] ? R : never;

or like this (3 dots)

type RestArgs<T extends any[]> = T extends [any, infer ...R] ? R : never;

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)

Metadata

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions