09160-hard-assign

Back

type Assign<T extends Record<string, unknown>, U extends any[]> = U extends [
  infer Origin extends object,
  ...infer Rest extends object[]
]
  ? Assign<AssignObject<T, Origin>, Rest>
  : Copy<T>;

type AssignObject<
  T extends object,
  U extends object,
  Common extends keyof T & keyof U = keyof T & keyof U
> = {
  [P in Common]: U[P];
} & {
  [P in Exclude<keyof T, Common>]: T[P];
} & {
  [P in Exclude<keyof U, Common>]: U[P];
};
type Copy<T> = {
  [P in keyof T]: T[P];
};

Solution by Vampirelee #32687

type Assign<T extends Record<string, unknown>, U extends any[]> = U extends [
  infer F,
  ...infer R
]
  ? F extends Record<string, unknown>
    ? Assign<Omit<T, keyof F> & F, R>
    : Assign<T, R>
  : Omit<T, never>;

Solution by vangie #32252

type Assign<
	T extends Record<string, unknown>, 
	Arr,
> = Arr extends [
		infer First extends Record<string, unknown>, 
		...infer Tail extends Record<string, unknown>[]
	] 
	? Assign<Omit<Omit<T, keyof First> & First, never>, Tail> 
	: T

Solution by jjswifty #31473

type Handle<T extends object[]> = T extends [infer F1, infer F2, ...infer R extends object[]] ? Handle<[{
  [K in keyof F1 | keyof F2]: K extends keyof F2 ? F2[K] : K extends keyof F1 ? F1[K] : never
}, ...R]> : T[0]

type Assign<T extends Record<string, unknown>, U extends object[], O = Handle<[T,...U]>> = O

Solution by moonpoet #31176

// ่งฃ็ญ”ใ‚’ใ“ใ“ใซ่จ˜ๅ…ฅ
type Flatten<T> = { [P in keyof T]: T[P]}

type Assign<T extends Record<string, unknown>, U extends unknown[]> =
  U extends [infer F, ...infer Rest]
    ? F extends Record<string, unknown> ?
      Assign<Omit<T, keyof F> & F, Rest>
    : Assign<T, Rest>
  : Flatten<T>

Assign<T, U> ใซๅฏพใ—ใ€U extends [infer F, ...infer Rest] ใจๅ…ˆ้ ญใ‚’ๆŠฝๅ‡บใ—ใ€T ใจ F ใ‚’ใƒžใƒผใ‚ธใ—ใพใ™ใ€‚ ใใฎ้š›ใ€Assign ใฏใ€key ใฎ้‡่ค‡ใŒใ‚ใฃใŸๅ ดๅˆใ€ๅพŒใ‚ใฎใ‚‚ใฎใ‚’ๅ„ชๅ…ˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจใ„ใ†่ฆ่ซ‹ใ‹ใ‚‰ใ€Omit<T, keyof F> & F ใฎใ‚ˆใ†ใซใ—ใพใ™ใ€‚

ๅ†ๅธฐใ‚’็นฐใ‚Š่ฟ”ใ—ใ€ๆœ€ๅพŒใซ U ใŒ [] ใจใชใฃใŸใจใ“ใ‚ใงใ€T ใ‚’่ฟ”ใ™ใฎใงใ™ใŒใ€T ใฏ & ใง็น‹ใŒใ‚ŒใŸใ‚‚ใฎใชใฎใงใ€Flatten<T> ใ‚’่ฟ”ใ—ใพใ™ใ€‚

ๅฅฝใฟใงใ™ใŒใ€

type Assign<T extends Record<string, unknown>, U extends unknown[]> =
  U extends [infer F, ...infer Rest]
    ? F extends Record<string, unknown> ?
      Assign<Flatten<Omit<T, keyof F> & F>, Rest>
    : Assign<T, Rest>
  : T

ใฎใ‚ˆใ†ใซใ€ใƒžใƒผใ‚ธใฎ้š›ใซ Flatten ใ‚’ๆŒŸใ‚“ใงใ‚‚ใ„ใ„ใจๆ€ใ„ใพใ™ใ€‚

Solution by Kakeru-Miyazaki #30978

// your answers
type MergeHelper<T1, T2> = { [K in keyof T2]: T2[K] } & { [K in keyof T1 as K extends keyof T2 ? never : K]: T1[K] }
type Merge<T1, T2> = { [K in keyof MergeHelper<T1, T2>]: MergeHelper<T1, T2>[K] }
type Assign<T extends Record<string, unknown>, U extends any[]> = U extends [infer F, ...infer Rest] ? F extends Record<any, any> ? Assign<Merge<T, F>, Rest> : T : T

Solution by AAA611 #28898

type Assign<T extends Record<string, unknown>, U> = U extends [
  infer F,
  ...infer R
]
  ? F extends object
    ? Assign<Omit<Omit<T, keyof F> & F, never>, R>
    : Assign<T, R>
  : T;

Solution by JohnLi1999 #26163

/**
 * ๆ€่ทฏ๏ผš
 *  1.ๅ…ˆๅพ—ๅˆฐๆ‰€ๆœ‰ๅฏน่ฑก็š„้”ฎ็ป„ๆˆ็š„่”ๅˆ็ฑปๅž‹,ๆœ€็ปˆ็ป“ๆžœtargetๆœ‰ไธ”ไป…ๆœ‰่ฟ™ไบ›็ฑปๅž‹
 *  2.ๅฐ†ๆ•ฐ็ป„[target,...source]่ฟ›่กŒ้€†ๅบ, ๆœ€็ปˆtarget้‡Œๆฏไธ€ไธชๅฑžๆ€ง็š„็ฑปๅž‹ๅบ”่ฏฅๆ˜ฏ็”จkeyๅœจ้€†ๅบๅŽ็š„ๆ•ฐ็ป„้‡Œ้กบๅบๆŸฅๆ‰พ๏ผŒๆ‰พๅˆฐ็š„็ฌฌไธ€ไธชๅ€ผ็ฑปๅž‹ๅณๆปก่ถณ่ฆๆฑ‚
 * 
 */
type Reverse<T extends object[], R extends object[] = []> =
    T extends [infer Item extends object, ...infer Rest extends object[]] ? Reverse<Rest, [Item, ...R]> : R

type FindFirstType<T extends object[], K extends keyof any> =
    T extends [infer Item extends object, ...infer Rest extends object[]] ? K extends keyof Item ? Item[K] : FindFirstType<Rest, K> : never

type GetAllKeys<T extends object[], U = never> =
    T extends [infer Item extends object, ...infer Rest extends object[]] ? GetAllKeys<Rest, U | keyof Item> : U


type Assign<T extends object, S extends object[], List extends object[] = Reverse<[T, ...S]>> = {
    [key in GetAllKeys<List>]: FindFirstType<List, key>
}

Solution by zhuizhui0429 #25881

type Assign<T extends Record<string, unknown>, U extends any[]> =
  U extends [infer F extends object, ...infer R extends object[]] ?
  Assign<{ [P in keyof T | keyof F]: P extends keyof F ? F[P] : P extends keyof T ? T[P] : never }, R> :
  T;

// old way
// type Combine<T extends object, U extends object> = { [P in keyof T | keyof U]: P extends keyof U ? U[P] : P extends keyof T ? T[P] : never };

// type Assign<T extends Record<string, unknown>, U extends [...any[]]> = U extends [infer F, ...infer R] ? F extends Record<string, unknown> ? Assign<Combine<T, F>, R> : T : T;

Solution by E-uler #25111

// your answers
type AssinItem<T extends object, U> = U extends object ? {
  [Key in (keyof T | keyof U)]: Key extends keyof U ? U[Key] : Key extends keyof T ? T[Key] : never
}: T

type Assign<T extends Record<string, unknown>, U extends any[]> = U extends [infer F, ...infer R] ?
Assign<AssinItem<T, F>, R> : T

Solution by snakeUni #24119

type Assign<T extends object, U extends object[] = [], Result extends object = T> = 
U extends [ infer F extends object,  ...infer R extends object[] ]
? Assign<
  {
    [K in keyof T | keyof F]: K extends keyof F ? F[K] : K extends keyof T ? T[K] : never
  },
  R
 >
: { [P in keyof Result]: Result[P] }

Solution by TKBnice #23549

// your answers
type FormatObj<T> = {
  [K in keyof T]: T[K]
}
type Assign<
  T extends Record<string, unknown>,
  U
> = U extends [infer F, ...infer Rest] 
    ? F extends Record<string, unknown> 
      ? Assign<FormatObj<Omit<T, keyof F> & F>, Rest>
      : Assign<FormatObj<T>, Rest>
    : T

Solution by jxhhdx #23289

type Merge<F, S> = {
  [Key in keyof F | keyof S]: Key extends keyof S ? S[Key] : Key extends keyof F ? F[Key] : never
}

type Assign<T extends Record<string, unknown>, U extends unknown[]> =
  U extends [infer A, ...infer Rest]
    ? Assign<A extends Record<string, unknown> ? Merge<T, A> : T, Rest>
    : T

Solution by drylint #22979

type Amalgm<U extends any[], Result extends Record<string, unknown>= {}> = U extends [infer F, ...infer Rest extends any[]] ? F extends object ? Amalgm<Rest, { [P in keyof Result] : P extends keyof F? F[P] : Result[P] } & { [P in keyof F as P extends keyof Result ? never : P] : F[P] }> :never

: U extends [] ? Result : never

type Assign<T extends Record<string, unknown>, U extends any[], K extends unknown = Amalgm > = U[number] extends object ? { [P in keyof K ] : K[P] } & { [P in keyof T as P extends keyof K? never : P] : T[P] } extends infer R ? { [P in keyof R]: R[P] } :never :T

Solution by amcguire704 #22499

type KeyOfObject<T> = keyof (T extends object ? T :  {});

type Assign<T extends Record<string, unknown>, U extends unknown[]> = U extends [infer F, ...infer Rest] ? Assign<{
  [key in (keyof T)|KeyOfObject<F>]: key extends keyof F ? F[key] : key extends keyof T ? T[key] : never
}, Rest> : T;

Solution by Karamuto #22229

type Keys<Sources extends any[] = []> = Sources extends [infer First, ...infer Rest]
  ? First extends Record<PropertyKey, unknown>
    ? keyof First | Keys<Rest>
    : never
  : never;

type GetCorrectValue<Key extends PropertyKey, Sources extends any[] = []> = Sources extends [...infer Rest, infer Last]
  ? Key extends keyof Last
    ? Last[Key]
    : GetCorrectValue<Key, Rest>
  : never;

type Assign<T, Sources extends any[] = []> = {
  [Key in keyof T | Keys<Sources>]: GetCorrectValue<Key, [T, ...Sources]>;
};

Solution by zqiangxu #22099

type AssignTwo<A extends Record<string, unknown>, B extends Record<string, unknown>, _AK extends keyof A = keyof A, _BK extends keyof B = keyof B> = {
  [P in _AK | _BK]: P extends _BK ? B[P] : P extends _AK ? A[P] : never
}

type Assign<T extends Record<string, unknown>, U extends unknown[]> = 
  U extends [infer First extends Record<string, unknown>, ...infer Rest]
  ? Assign<AssignTwo<T, First>, Rest>
  : T

playground

fake hard

Solution by zhaoyao91 #22025

// your answers
type AssignOne<F, S> = Org<Omit<F, keyof S> & S>
type Org<T> = {
  [K in keyof T] : T[K]
}
type Assign<T extends Record<string, unknown>, U> = U extends object[]
  ? U extends [infer F, ...infer R]
    ? Assign<AssignOne<T, F>, R>
    : T
  : T;

Solution by YqxLzx #21974

type GetAllRecordKeys<T extends Array<Record<string, unknown>>> = T extends [
  infer A,
  ...infer B extends Array<Record<string, unknown>>
]
  ? keyof A | GetAllRecordKeys<B>
  : never;

type GetLastRecordValue<T, Key> = T extends [...infer A, infer B]
  ? Key extends keyof B
    ? B[Key]
    : GetLastRecordValue<A, Key>
  : never;

type DemotionRecords<
  T extends Array<Record<string, unknown>>,
  Key
> = T extends [infer A, ...infer B extends Array<Record<string, unknown>>]
  ? [MaybeInKey<A, Key>, ...DemotionRecords<B, Key>]
  : [];

type MaybeInKey<T, Key> = Key extends keyof T
  ? T[Key] extends Record<string, any>
    ? T[Key] extends Array<any>?{}:T[Key]
    : {}
  : {};

type Assign<
  T extends Record<string, unknown>,
   U extends Array<any>
> = {
  [P in keyof T | GetAllRecordKeys<U>]: GetLastRecordValue<
    [T, ...U],
    P
  > extends Record<string, any>
    ? GetLastRecordValue<[T, ...U], P> extends Array<any>
      ? GetLastRecordValue<[T, ...U], P>
      : Assign<MaybeInKey<T, P>, DemotionRecords<U, P>>
    : GetLastRecordValue<[T, ...U], P>;
};

Solution by so11y #21330

type Assign<T extends Record<string, unknown>, U extends unknown[]> =
  U extends [ infer F, ...infer Rest extends Record<string, unknown>[] ]
    ? F extends Record<string, unknown>
      ? Assign<Omit<T, keyof F> & F, Rest>
      : never
    : { [P in keyof T]: T[P] }

Solution by lvjiaxuan #20718

type Assign<
  T extends Record<string, unknown>,
  U extends unknown[]
> = U extends [infer A, ...infer B]
  ? A extends Record<string, unknown>
    ? Assign<
        {
          [K in keyof T | keyof A]: K extends keyof A
            ? A[K]
            : K extends keyof T
            ? T[K]
            : never
        },
        B
      >
    : Assign<T, B>
  : T

Solution by theoolee #19807

type Assign<T extends Record<string, unknown>, U extends unknown[]> =
  U extends [infer F, ...infer R]
    ? Assign<F extends Record<string, unknown> ? { [key in keyof T | keyof F]: key extends keyof F ? F[key] : T[key & keyof T] } : T, R>
    : T;

Solution by kimsangyeon #19348

// your answers
type SelfMerge<T extends Record<string, any>, R extends Record<string, any>> = {
    [K in (keyof R | keyof T)]: K extends keyof R ? R[K] 
                                    : K extends keyof T 
                                        ? T[K]
                                        : never; 
};

type Assign<T extends Record<string, unknown>, U extends any[], Result extends Record<string, any> = T> = U extends [infer R, ...infer J]
                                                                                    ? R extends Record<string,any> 
                                                                                        ? Assign<T, J, SelfMerge<Result, R>>
                                                                                        : Assign<T, J, Result>
                                                                                    : Result;

Solution by jiaaoMario #17507

type Merge<T, U> = U extends Record<string, unknown>
  ? { [R in keyof T | keyof U]: R extends keyof U ? U[R] : R extends keyof T ? T[R] : never }
  : T
type Assign<T extends Record<string, unknown>, U extends unknown[]> = U extends [infer P, ...infer R]
  ? Assign<Merge<T, P>, R>
  : T

Solution by xjq7 #17280

type Assign<T extends Record<string, unknown>, U extends unknown[]> =
  U extends [infer F, ...infer R]
    ? Assign<F extends object ? { [P in keyof T | keyof F]: P extends keyof F ? F[P] : T[P & keyof T] } : T, R>
    : T;

Solution by BulatDashiev #16977

type ObjectAssign<Target extends object, Origins extends object[]> = Origins extends [infer Origin1, ...infer OriginRest] ? OriginRest extends object[] ? ObjectAssign<{ [K in (keyof Target) | (keyof Origin1)]: K extends keyof Origin1 ? Origin1[K] : K extends keyof Target ? Target[K] : never }, OriginRest> : never : Target;

Solution by my5201314zwl #16938

// your answers

type AllowArgs<T extends unknown[], Result extends Record<string, unknown>[] = []> = T extends [infer F, ...infer R]
  ? F extends Record<string, unknown>
    ? AllowArgs<R, [...Result, F]>
    : AllowArgs<R, Result>
  : Result

type MergeInterface<
  T extends Record<string, unknown>,
  D extends Record<string, unknown>
> = {
  [P in keyof T | keyof D]: P extends keyof D
    ? D[P]
    : P extends keyof T
      ? T[P]
      : never
}

type Assign<
  T extends Record<string, unknown>,
  U extends unknown[],
  D extends Record<string, unknown>[] = AllowArgs<U>
> = D extends [infer F extends Record<string, unknown>, ...infer R extends Record<string, unknown>[]]
  ? Assign<MergeInterface<T, F>, never, R>
  : T

Solution by humandetail #16555

// your answers
type ObjectIntersection<
    T extends object, 
    U extends any[] > = 
    U extends [infer R extends object,...infer U extends object[]]
    ? ObjectIntersection<{[J in keyof T|keyof R] : J extends keyof R ? R[J] : J extends keyof T ? T[J] : never},U>
    : T ;

type Merge<
    T extends object> =
    {[J in keyof T] : T[J]};

type Assign<T extends object, 
    U extends any[] > =
    Merge<ObjectIntersection<T,U>> ;

Solution by justBadProgrammer #16074

// your answers
type Merge<F, S> = {
    [K in keyof F | keyof S]: K extends keyof S ? S[K] : K extends keyof F ? F[K] : never
}

type Assign<T extends Record<string, unknown>, U> = U extends [infer K, ...infer R]
    ? K extends Record<string, unknown>
        ? Assign<Merge<T, K>, R>
        : Assign<T, R>
    : T

Solution by huangyuanjin #15345

type Assign<T extends Record<string, unknown>, U> = U extends [infer L, ...infer R]
    ? L extends Record<string, unknown>
        ? Assign<
              {
                  [P in keyof T | keyof L]: P extends keyof L
                      ? L[P]
                      : P extends keyof T
                      ? T[P]
                      : never;
              },
              R
          >
        : T
    : T;

Solution by Cookeke #14417