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
Variadic with "named tuples" doesn't preserve name #39941
Comments
@ahejlsberg any idea how feasible this would be? One problem is you don't know whether two spread instantiations will end up with identical names. |
In most use case, names should be unique. My proposal: [...[foo: number, bar: boolean], foo: string] // --> [foo: number, bar: boolean, foo_2: string]
[...[...[foo: number, bar: boolean], foo: string], foo: string] // --> [foo: number, bar: boolean, foo_2: string, foo_3: string]
[foo: string, ...[foo: number, bar: boolean]] // --> [foo: string, foo_2: number, bar: boolean] |
Setting aside the generic case, having name preservation for simpler cases would be great:
This doesn't error on playground because of #40118, which landed after 4.0.2. |
I hit the same problem. I found an ugly workaround which looks like this: |
We already support giving names to variadic elements, and the original example works as expected when you do so: type Append<I, T extends unknown[]> = [...first: T, last: I];
type FooBar = Append<string, [foo: number, bar: boolean]>; // [foo: number, bar: boolean, last: string]
type FooBaz = Append<string, number[]>; // [...first: number[], last: string] Note that when a variadic element is instantiated with a tuple type, the individual element names of that tuple type override the name of the variadic element. All in all, I don't think any new features or changes are needed here. |
What do you mean by that exactly? Take a look at the following example: type Input = [first: string, second: number];
type Append<A extends unknown[], B extends unknown[]> = [...A, ...B];
type AppendInPlaceWithSpread<A extends unknown[]> = [...A, ...[third: boolean]];
type AppendInPlaceWithoutSpread<A extends unknown[]> = [...A, third: boolean]; // Error: Tuple members must all have names or all not have names.
// Works as expected, element names are preserved
type Result1 = Append<Input, [third: boolean]>; // [first: string, second: number, third: boolean]
// Element names are lost
type Result2 = AppendInPlaceWithSpread<Input>; // [string, number, boolean] What's the difference between I also noticed that if we name the first variadic element in the following way, everything works as expected: type Append<A extends unknown[]> = [...abc: A, third: boolean] But here the label |
The point is that the name is used when the variadic element is instantiated with an array type such as In general, our rule for checking that either all or none of the elements are named isn't perfect when variadic elements are involved because we can't really know whether instantiations will provide names or not. We could potentially consider getting rid of that rule since names have no semantic meaning and it doesn't really matter if something is only partially named. |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
This follows [1], in order to keep the label of each argument. [1]: 33e4172 Related: - #1570 (comment) - microsoft/TypeScript#39941 - microsoft/TypeScript#48049
I know it's closed but for anyone searching for a way of "patching" Variadic tuple types while keeping names I found a easy workaround! It's basicaly assigning the typle to a new function, patching the function parameters, and returning the parameters of this function. Exemple I had for a Vue lib: import type {Ref} from 'vue';
type CreateFn<T extends any[]> = (...args: T) => any;
export type PatchTuple<T extends any[], F = CreateFn<T>> = Parameters<
F extends (...args: infer Args) => any
? (
...args: {
[K in keyof Args]: Ref<Args[K]>;
}
) => any
: never
>;
type MyTuple = [foo: string, bar?: Date];
type patched = PatchTuple<MyTuple>; // [foo: Ref<string>, bar?: Ref<Date | undefined>] |
Not sure this actually should be possible... I guess it would get funky as typescript would have to deal with naming conflicts.
TypeScript Version: 4.1.0-dev
Search Terms:
Variadic, Named Tuples
Code
Expected behavior:
Should preserve named tuples labels:
type FooBar = [foo: number, bar: boolean, last: string]
Actual behavior:
type FooBar = [number, boolean, string]
Playground Link:
https://www.typescriptlang.org/play?ts=4.0.0-beta#code/C4TwDgpgBAgmkDsAmAeAkgGigFShAHsBMgM5QCuCA1ggPYDuCA2gLoB8UAvFEwHT-YsAGwCGJYAC40LANwAoUJCgAxWrQBCIgE5dY8YqnFaAlggDmWJgDM1EqAnIBbAEYQtWZ9rvO1QiCIR2OSA
Related Issues:
none
The text was updated successfully, but these errors were encountered: