You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tuple & nominal not recognised as tuple in spread parameter #45371
declareleta: [number,number,number]&{_nominal_a: never}functionb(...params: [number,number,number]){}b(...a)// Error: A spread argument must either have a tuple type or be passed to a rest parameter.
🙁 Actual behavior
The error in the code example is thrown, because TypeScript does not detect it as being a tuple.
In roblox-ts, we use a nominal marker type to indicate a special kind of tuple. This bug means that this tuple type can then not be spreaded into a fixed argument function. Our issue: roblox-ts/roblox-ts#1537
🙂 Expected behavior
This is a tuple type, and should therefore be recognised as such.
What I find somewhat trubling, beyond TypeScript loosing the plot in the first place, is that Array<T> will produce the same error, eg.
This usually makes sense, because you don't know the Array's length, which is why it's (as the correct behaviour) not considered a tuple.
That's part 1, and then part 2, I believe this not working in this case is a separate missing behaviour, which is that normal parameters need to be filled manually, not being considered to be part of the rest parameter. What I mean by that is that a function like a(obj: object, ...other: object[]) will not allow a call like a(...objects) where objects is Array<object>, despite this being type-compatible.
Hmm, I supose I'll have to dig deeper into how TypeScript parses things. Because I'm still a bit befuddled that as Array<{ [key: string]: unknown }> throws errors but using the same hint for a parameter doesn't present issues, eg.
functionmergeDictionaries(
...dictionaries: Array<{[key: string]: unknown}>/* ← Totally okay */// ...dictionaries: [{ [key: string]: unknown }] /* ← this is fine too */): {[key: string]: unknown;}{returnObject.assign(
...(dictionaries.map((dictionary)=>{returnJSON.parse(JSON.stringify(dictionary));})as[{[key: string]: unknown}])// }) as { [key: string]: unknown }[]) /* ← Nope */// }) as Array<{ [key: string]: unknown }>) /* ← no joy either */);}
I'm mapping a dispatch into a object and this is freaking my mind.
// not actual example but closeObject.fromEntries(Object.entries(actions).map(entry=>[entry[0],(...args: Parameters<typeofentry[1]>)=>dispatch(entry[1](...args))]))
There is no reason for that be a problem, mainly because not allowing arrays as spread arguments should be a linter problem, not a compiler problem.
Made a Playground Link for your code example, and I'm failing to spot any issue in this. In any case, it's probably similar to the above comment by S0AndS0, and as explained not a related problem.
I am not sure if this is related, or supposed to occur... However, when attempting to brand or flavor a tuple it appears that TypeScript is no longer able to restrict property access past the length of the tuple.
Example
declareconstid: unique symbol;typeId<T>={readonly[id]: T};typeBrand<T,U>=T&Id<U>;typePartialBrand<T,U>=T&Partial<Id<U>>;// Also known as Flavor.declareconstpointId: unique symbol;typePoint=PartialBrand<[number,number],typeofpointId>;constpoint=(x: number=0,y: number=0): Point=>[x,y];constadd=(a: Point,b: Point,c: Point=point()): Point=>{c[0]=a[0]+b[0];c[1]=a[1]+b[1];returnc;};consta=point(0,1);constb=point(2,3);constc=add(a,b);console.log(c);c[0]=4;c[1]=5;c[2]=6;// Should be an error!console.log(c);
Here is another instance of (probably) the same error: Playground link
A TS2556 (A spread argument must either have a tuple type or be passed to a rest parameter.) error is thrown whenever I try to spread the contents of a tuple into another function. Even though that tuple is inferred as the correct type.
I have tested this on all versions available in the playground.
// https://stackoverflow.com/a/66252656typeRemoveIndex<T>={[KinkeyofTasstringextendsK
? never
: numberextendsK
? never
: symbolextendsK
? never
: K] : T[K];};// -snip-typePartialBrand<T,U>=RemoveIndex<T>&Partial<Id<U>>;// Also known as Flavor.// ^^^^^^^^^^^
Activity
S0AndS0 commentedon Dec 31, 2021
I recently ran into this error too, and worked around it by hinting the type via the
askeyword, eg.... without the
[{ [key: string]: unknown }])bit, an error similar to the following pops;What I find somewhat trubling, beyond TypeScript loosing the plot in the first place, is that
Array<T>will produce the same error, eg.Dionysusnu commentedon Dec 31, 2021
This usually makes sense, because you don't know the Array's length, which is why it's (as the correct behaviour) not considered a tuple.
That's part 1, and then part 2, I believe this not working in this case is a separate missing behaviour, which is that normal parameters need to be filled manually, not being considered to be part of the rest parameter. What I mean by that is that a function like
a(obj: object, ...other: object[])will not allow a call likea(...objects)whereobjectsisArray<object>, despite this being type-compatible.S0AndS0 commentedon Jan 1, 2022
Hmm, I supose I'll have to dig deeper into how TypeScript parses things. Because I'm still a bit befuddled that
as Array<{ [key: string]: unknown }>throws errors but using the same hint for a parameter doesn't present issues, eg.darklight9811 commentedon Jan 12, 2022
I'm mapping a dispatch into a object and this is freaking my mind.
There is no reason for that be a problem, mainly because not allowing arrays as spread arguments should be a linter problem, not a compiler problem.
Dionysusnu commentedon Jan 13, 2022
Made a Playground Link for your code example, and I'm failing to spot any issue in this. In any case, it's probably similar to the above comment by
S0AndS0, and as explained not a related problem.scottwillmoore commentedon Apr 23, 2022
I am not sure if this is related, or supposed to occur... However, when attempting to brand or flavor a tuple it appears that TypeScript is no longer able to restrict property access past the length of the tuple.
Example
Playground Link
It appears that the expansion of the type includes
[x: number]: number. Maybe I should open this a separate issue?TomRaaff commentedon Aug 21, 2023
Here is another instance of (probably) the same error:
Playground link
A TS2556 (A spread argument must either have a tuple type or be passed to a rest parameter.) error is thrown whenever I try to spread the contents of a tuple into another function. Even though that tuple is inferred as the correct type.
I have tested this on all versions available in the playground.
RA80533 commentedon Feb 21, 2024
Scott Moore (@scottwillmoore) Good observation. Once the index signature is removed, the tuple behaves as expected.
Playground link
Playground link