-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Tuple iteration and merging #26058
Comments
I don't think this is correct. It should behave like object spread in JS and override existing properties. type T = {... {a: string}, ...{a: number}};
// should result in
type T = {a: number};
// instead of
type T = {a: string} & {a: number}; |
@ajafff Fixed by removing the line. I forgot about that bit. |
@AlCalzone For the first half, probably, but the second half is likely not. |
See also #5453 for part 1. |
BTW, I updated the proposal to leverage this recently-merged PR. |
Doesn't type TupleTypes<T extends unknown[]> = T[number] ? |
@weswigham Good catch - no clue how that escaped me. I updated the proposal comment to drop that (and those covered by #26063), but the issue with concatenation and I changed up the proposed syntax a little, too, to better fit in:
Of course, that space in the middle isn't significant, just explains how it's tokenized. |
Ignoring tuples for a second, I want a way to easily convert any union to an intersection. But y'know, I think it is doable, if cumbersome: type MergeArguments<T, K extends string = "whatever"> =
{
[Key in K]: T extends (first: infer A) => void ? A :
MergeOnePlus<T, K>
}[K];
type MergeOnePlus<T, K extends string> =
{
[Key in K]: T extends (first: infer A, ...args: infer U) => void ? A & MergeArguments<(...args: U) => void, K> :
never
}[K];
type IntoSignature<T extends unknown[]> = (...args: T) => void;
type MergeTupleMembers<T extends unknown[]> = MergeArguments<IntoSignature<T>>;
type SomeTuple = [{ x: 1 }, { y: 2 }, { z: 3 }];
type Merged = MergeTupleMembers<SomeTuple>;
const x: Merged = {
x: 1,
y: 2,
z: 3
}; It's a bit ridiculous, but.... possible. |
@weswigham That might very well solve the issue of both concatenation and merging, if I'm reading it correctly. By any chance, would that still work if you did this to do concatenation? type ConcatenateOnePlus<T, K extends string> =
{
[Key in K]: T extends (first: infer A, ...args: infer U) => void ? [A, ...ConcatenateArguments<(...args: U) => void, K>] :
never
}[K]; |
@weswigham check this out: /**
* @author https://stackoverflow.com/users/2887218/jcalz
* @see https://stackoverflow.com/a/50375286/10325032
*/
type UnionToIntersection<Union> =
(Union extends any
? (argument: Union) => void
: never
) extends (argument: infer Intersection) => void
? Intersection
: never; |
I'm working on a utility lib with Merg(Intersection), object only Merg, the well-known symbol iterator walkaround. and type morphing. Please check if they are okay. (this is my first ts lib) export type Omit2<T, K extends keyof T> = T extends { [Symbol.iterator]: infer U } ? { [Symbol.iterator]: U } & Omit<T, K> : Omit<T, K>;
export type ExcludeO<T extends object, U extends object> =
U extends { [Symbol.iterator]: any } ? Omit<T, keyof U> :
T extends { [Symbol.iterator]: infer IT } ? { [Symbol.iterator]: IT } & Omit<T, keyof U> : Omit<T, keyof U>;
export type ExtractO<T extends object, U extends object> =
U extends { [Symbol.iterator]: any } ? T extends { [Symbol.iterator]: infer IT } ?
{ [Symbol.iterator]: IT } & Pick<T, Extract<keyof T, keyof U>> :
Pick<T, Extract<keyof T, keyof U>> : Pick<T, Extract<keyof T, keyof U>>;
export type Merg<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
export type MergO<U extends object> = (U extends object ? (k: U) => void : never) extends (k: infer T) => void ?
(T extends object ? T : object) : object;
export type UnionTupleType<A extends any[]> = A extends { [n: number]: infer T } ? T extends object ? T : never : never;
export type MergTupleType<A extends any[]> = MergO<UnionTupleType<A>>;
export type Alter<T extends object, U extends object> = ExcludeO<T, U> & ExtractO<U, T>;
export type Extend<T extends object, U extends object> = T & ExcludeO<U, T>;
export type Override<T extends object, U extends object> = ExcludeO<T, U> & U;
export type AlterOver<T extends object, U extends object, X extends object> = Alter<T, ExcludeO<U, X>>;
export type ExtendOver<T extends object, U extends object, X extends object> = Extend<T, ExcludeO<U, X>>;
export type OverrideOver<T extends object, U extends object, X extends object> = Override<T, ExcludeO<U, X>>;
export type AlterLike<T extends object, U extends object, X extends object> = Alter<T, ExtractO<U, X>>;
export type ExtendLike<T extends object, U extends object, X extends object> = Extend<T, ExtractO<U, X>>;
export type OverrideLike<T extends object, U extends object, X extends object> = Override<T, ExtractO<U, X>>; |
@weswigham this should fit your need and it enforces object export type MergO<U extends object> = (U extends object ? (k: U) => void : never) extends (k: infer T) => void ? (T extends object ? T : object) : object;
export type UnionTupleType<A extends any[]> = A extends { [n: number]: infer T } ? T extends object ? T : never : never;
export type MergTupleType<A extends any[]> = MergO<UnionTupleType<A>>; |
@lieene That is wild! What is going on with the functions in |
Edit: Remove indexing part
Edit 2: Replace tuple mapping syntax with normal mapped types
Search Terms
Concatentate and merge tuples' entries.
Suggestion
Use Cases
Object.assign
's assignee.Array.prototype.concat
correctly for tuples.Syntax
The syntax comes in a few new forms:
[...A, B]
appendsB
to the tupleA
. Similarly,[...infer A, any] extends B ? A : []
drops the last item of the tuple and[...any[], infer A] extends B ? A : never
extracts the first.{... ...T}
for an n-ary merge and[... ...T]
an n-ary concatenation.Examples
Here's the types for each method I mentioned above.
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: