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 https://github.com/Microsoft/TypeScript/pull/24897
Actual behavior: Failed with _TS2574: A rest element type must be an array type._
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.
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._
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
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.
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.
This is now implemented in #39094.
Most helpful comment
A minimal example showing the non-symmetricity of function arguments vs. tuple types.
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