Repository navigation
ReadonlyArray with rest parameters #15972
Description
Activity
- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensus
on May 22, 2017 This limitation makes harder to use tslint-immutable package.
https://www.npmjs.com/package/tslint-immutableReacted by Davy Duperron, Marco Lüthy, Mark Pradhan, Danilo Spinelli, Sergey Shandar, Jonas Kello, Max Sysoev, Arnau Orriols and André MazoniIs the following the right place to start with implementing a fix?
There are a few places where we make an assumption about rest params being the
globalArrayType, we will need to look at them all and fix them. one place is for example any use ofisArrayTypewith rest params.Union and intersections are another example (See #23440).
function dist(x1: number, y1: number, x2: number, y2: number): number function dist(point1: point, point2: point): number function dist(...args: number[] | point[]): number { // function body }
Reacted by Alexander Kachkaev, sam-s4s, Jesse McCarthy and Boyangalexander-alvarez commented
on May 21, 2018 More actionsI think I'm hitting the same issue when I do something like this:
declare interface R { a: [string, number], b: [boolean] } declare function on<T extends keyof R, K extends R[T]>(val: T, listener: (...args: K) => void): void; // rest parameter must be array type ^ in ...args on('b', (a) => { })
as a workaround I've had to not use the splat args, and overload the method for each arity
Reacted by Michael Sanford, Anton Zinovyev and Keegan FarleyThis is also an issue for conditional types inside generic class methods
class Foo <T> { bar(...args: T extends number ? number[] : string[]): void { // A rest parameter must be of an array type. } }Yeah I've just run into this issue...
remove(...items: (M[] | number[])) {}The above code should work, but does not :(
There is a temporary work around for some of the issues mentioned here, specifically the union types, until problem is resolved
type F1 = (...args: number[] | string[]) => any; // Throws an error type Fof<T extends any[], R> = (...args: T) => R; type F2 = Fof<number[] | string[], any>; // Compiles without error
It's not clear to me why this fix works. As you can see in the screenshot below, the type of
F2is(...args: number[] | string[]) => anyeven though that type is apparently an error.Reacted by Alec Larson and Tomás Foxtype Fof<T extends any[], R> = (...args: A) => R;
You meant 'T' and not 'A' I guesstype Fof<T extends any[], R> = (...args: T) => R;
Reacted by Jesse McCarthy, Johannes Homeier, Michael Sanford and BeraYa
type Fof<T extends any[], R> = (...args: A) => R;
You meant 'T' and not 'A' I guesstype Fof<T extends any[], R> = (...args: T) => R;
Ya I did thanks for pointing that out 👍
I have another (albeit slightly dysfunctional) use case impacted by this. Using Typescript 3.1.0-rc.
class Pipeline<PS extends any[]> { // Gives error: // // A rest element type must be an array type. // // NOTE: Technically incorrect because `PS` includes `PS[0]` // public constructor(fns: [HeadFn<PS[0]>, ...TailFns<PS>]) { } } interface HeadFn<T> { kind: 'head' props: T } interface TailFn<T> { kind: 'tail' props: T } type TailFns<TS> = { [K in keyof TS]: TailFn<TS[K]> }
Same error with a stronger restriction on the
TailFnstype parameter:type TailFns<TS extends any[]> = { [K in keyof TS]: TailFn<TS[K]> }
Reacted by Alec Larson and Nikita NitichevskiOf note, this is also an issue with tuple splat types in typescript > 3.0.
i.e.
// works function tuple<T extends any[]>(...value: T) { return value } // compile error function tuple<T extends ReadonlyArray<any>>(...value: T) { return value }Reacted by Alec Larson and Bera... same for TS 3.0 "Rest elements in tuple types":
type MyTuple1 = [string, ...string[]]; // Error in TS 3.0/3.1: type MyTuple2 = [string, ...ReadonlyArray<string>];
(I didn't find an own issue for that.)
Reacted by Joshua ColeSubscribing for this
For those that land here like I did and think they need to use the Fof<> workaround above, in my case it was much easier. I had this:
add: (...items: T[] | Enum<T>[]) => void;Which I just needed to change to:
add: (...items: (T | Enum<T>)[]) => void;Might be obvious to all but noobs, but since this was the first hit on Google when I searched on the error message, safe to say I'm not the only noob reading this.
ericselkpc It may not matter terribly much, but I'd just like to point out that this solution has one technical problem - it allows mixed arrays... ie. an array that contains items of both type T and type Enum... This may cause problems if you're not careful :)
Reacted by ericselkpc and Keegan Farleyericselkpc your first example now works in 3.3, my example above also now works.
Looks like this issue was fixed in #29435
See #29435 (comment)
/cc Anders Hejlsberg (@ahejlsberg) Daniel Rosenwasser (@DanielRosenwasser)
Reacted by SlurpTheo, Mehdi Lahlou, Alex Alvarez, Julien Quéré and Mathieu M-Gosselin- addedCommittedThe team has roadmapped this issueThe team has roadmapped this issueand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Feb 25, 2019

I expect all three functions to be compiled successfully.
TypeScript doesn't allow using ReadonlyArray although it is the same as Array but readonly.