Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rest elements in generic tuple #26113

Closed
vmit opened this issue Aug 1, 2018 · 6 comments · Fixed by #39094
Closed

Rest elements in generic tuple #26113

vmit opened this issue Aug 1, 2018 · 6 comments · Fixed by #39094
Labels
Fix Available A PR has been opened for this issue In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@vmit
Copy link

vmit commented Aug 1, 2018

TypeScript Version: 3.1.0-dev.20180801

Search Terms: spread tuple

Code

interface Foo<ArgsT extends any[]> {}

interface Bar<SubArgsT extends any[]> extends Foo<[number, ...SubArgsT]>{ }

Expected behavior: Successful compilation. Array subclasses are not allowed as rest arguments for now, but when it is about generics I expect behavior similar to what is done in #24897

Actual behavior: Failed with TS2574: A rest element type must be an array type.

@AlCalzone
Copy link
Contributor

AlCalzone commented Aug 1, 2018

Interstingly, adding angled brackets works (but requires an array of arrays following the number):

interface Foo<ArgsT extends any[]> {
	arr: ArgsT;
}

interface Bar<SubArgsT extends any[]> extends Foo<[number, ...SubArgsT[]]>{ }

var f: Foo<number[]> = {
	arr: [1,2,3],
};

var b1: Bar<string[]> = {
	arr: [1, [""], ["1", "2"]], // not what OP meant, but it works
}
var b2: Bar<string[]> = {
	arr: [1, "", "1", "2"], // error: [number, string, string] cannot be assigned to [number, ...string[][]]
}

And this correctly captures the type OP wants to create

type Fooify<SubArgsT extends any[]> = 
	((arg1: number, ...rest: SubArgsT) => any) extends ((...args: infer R) => any)
	? Foo<R> : never;

but an interface cannot extend that.

@mhegazy mhegazy added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Aug 2, 2018
@McPrescott
Copy link

Similarly, it seems that following the last example of @AlCalzone that rest element types should be able to be inferred without having to use a functions parameter list like so:

type dropFirst<T extends any[]> = 
    T extends [any, ...(infer U)] ? U : T;
// Instead of
type dropFirst<T extends any[]> = 
    ((...args: T) => any) extends (arg: any, ...rest: infer U) => any ? U : T;

But the same error occurs: A rest element type must be an array type.

@m93a
Copy link

m93a commented Oct 16, 2018

A minimal example showing the non-symmetricity of function arguments vs. tuple types.

declare function foo<T0, T extends any[]>(a: T0, ...b: T); // works
type foo<T0, T extends any[]> = [T0, ...T]; // rest element type must be an array type

I think this should be supported and it seems as an oversight to me that it isn't in 3.1 already.
Is there a specific reason for it to be disallowed, or is it just that it wasn't top priority?


Also, it took me quite a long time to find this issue, so I'm adding a few keywords.
Keywords: spread a generic tuple in a tuple type, generic tuple rest parameter in a tuple type, spreading array type in type declaration, T extends any[] does not work in tuple literal

@paul-marechal
Copy link

paul-marechal commented Aug 25, 2019

I would like to extend this issue for code looking like the following:

function meh<T>(...args: Extract<T, any[]>) {} // works
type Meh<T> = [...Extract<T, any[]>] // does not work (bug?)

Hopefully this all boils down to the same actual bug.

@ghost
Copy link

ghost commented Jan 24, 2020

This still seems to be an issue. I have the simple case:

type Combine<T, U> = U extends unknown[] ? [T, ...U] : never;

Which fails currently because it can't determine that U is valid as a rest parameter.

@ahejlsberg
Copy link
Member

This is now implemented in #39094.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants