13580-hard-replace-union

Back


// T ไธบ้ž่”ๅˆ็‰ˆๆœฌ
type ReplaceOne<T, U extends [any, any][]> = U extends [
  infer L,
  ...infer R extends [any, any][]
]
  ? L extends [infer Origin, infer Target]
    ? Equal<Origin, T> extends true
      ? Target
      : ReplaceOne<T, R>
    : never
  : T;

type UnionReplace<T, U extends [any, any][]> = T extends any
  ? ReplaceOne<T, U>
  : never;

Solution by Vampirelee #32693

type UnionReplace<T, U extends [any, any][]> = U extends [
  infer L extends [any, any],
  ...infer R extends [any, any][]
]
  ? L[0] extends T
    ? UnionReplace<Exclude<T, L[0]> | L[1], R>
    : UnionReplace<T, R>
  : T;

Solution by vangie #32255

type UnionReplace<T, U extends any[]> = U extends [infer F, ...infer R]
  ? F extends [infer F1, any]
    ? T extends F1
      ? F[1]
      : UnionReplace<T, R>
    : UnionReplace<T, R>
  : T;

Solution by moonpoet #31550

type Pair = [unknown, unknown];

type UnionReplace<T, U extends Pair[]> = 
  U extends [[infer Replaceable extends T, infer Replacement], ...infer RestPairs extends Pair[]] 
  ? UnionReplace<Replacement | Exclude<T, Replaceable>, RestPairs> : T

Solution by jjswifty #31125

// your answers

type UnionIn<T, U extends [any, any]> = T extends T ? U extends U ? T extends U[0] ? U[1] : never : unknown : unknown

type UnionEx<T, U extends [any, any]> = T extends T ? U extends U ? T extends U[0] ? never : U[0] : unknown : unknown

type UnionReplace<T, U extends [any, any][]> = Exclude<T, UnionEx<T, U[number]>> | UnionIn<T, U[number]>

Solution by 437204933 #29722

type Replace<T, U extends [any,any][]> = 
  U extends [
    infer F extends [any,any],
    ...infer R extends [any,any][]
  ]? 
    T extends F[0]?
      F[1]:
      Replace<T,R>
    :never
  
type UnionReplace<T, U extends [any, any][]> = 
  T extends any?
    T extends U[number][0]?
      Replace<T,U>:T
    :never

Solution by jiangshanmeta #27914

type Replace<T, U extends [unknown, unknown]> = T extends U[0] ? U[1] : T;

type UnionReplace<T, U extends [any, any][]> = U extends [
  infer F extends [unknown, unknown],
  ...infer R extends [unknown, unknown][]
]
  ? UnionReplace<Replace<T, F>, R>
  : T;

Solution by JohnLi1999 #26219

type UnionReplace<T, U extends [any, any][], V = T> =
  V extends T ?
  (
    U extends [[infer F, infer S], ...infer R extends any[]] ?
    (Equal<V, F> extends true ? S : UnionReplace<V, R>) | UnionReplace<Exclude<T, V>, U> :
    V
  ) :
  never;

// old way
// type UnionToIntersection<T> = (T extends T ? (arg: T) => any : never) extends (arg: infer P) => any ? P : never;
// type UnionLast<T> = UnionToIntersection<T extends T ? () => T : never> extends () => infer R ? R : never;

// type ForEachReplace<T, U extends [any, any][]> = U extends [infer F extends [any, any], ...infer R extends [any, any][]] ?
//   (Equal<T, F[0]> extends true ? F[1] : ForEachReplace<T, R>) :
//   T;

// type UnionReplace<T, U extends [any, any][]> = [T] extends [never] ? never : ForEachReplace<UnionLast<T>, U> | UnionReplace<Exclude<T, UnionLast<T>>, U>;

Solution by E-uler #25137

type ReplaceOptions = [any, any][]

type Zip<T extends ReplaceOptions, Acc extends [any[], any[]] = [[],[]]> = 
  T extends [[infer Old, infer New],...infer Tail extends [any, any][]]
  ? [...(Acc extends [infer ArrOld extends any[], infer ArrNew extends any[]] ? Zip<Tail, [[...ArrOld,Old],[...ArrNew,New]]> : never)]
  : Acc

type UnionReplace<T, U extends ReplaceOptions> = 
  Zip<U> extends [infer Old extends any[], infer New extends any[]] 
  ? (T extends Old[number] ? never : T) | New[number]
  : never

Solution by Derstilon #24364

// your answers
type Replace<T, U, K> = T extends U ? K : T

type UnionReplace<T, U extends [any, any][]> = U extends [infer F, ...infer R extends [any, any][]] ? 
F extends [infer A, infer B] ? UnionReplace<Replace<T, A, B>, R> : T : T

Solution by snakeUni #24200

// your answers
type UnionReplace<T, U extends [unknown, unknown][]> =
  U extends [[infer A, infer R], ...infer Rest extends [unknown, unknown][]]
    ? T extends A
      ? R
      : UnionReplace<T, Rest>
    : T

Solution by jxhhdx #23170

type UnionReplace<T, U extends [unknown, unknown][]> =
  U extends [[infer A, infer R], ...infer Rest extends [unknown, unknown][]]
    ? T extends A
      ? R
      : UnionReplace<T, Rest>
    : T

Solution by drylint #23001

type UnionReplace<T, U extends [unknown, unknown][]> = 
  U extends [[infer Subject, infer Replacement], ...infer Rest extends [unknown, unknown][]] ? (
    UnionReplace<
      (T extends Subject ? never : T) |           // remove Subject
      (Subject extends T ? Replacement : never),  // add Replacement
      Rest
    >
  ) : T

Playground

Solution by teamchong #22543

// your answers
type UnionReplace<T, U extends [any, any][]> = U extends [infer F, infer L][]? T extends F ? 
Exclude<T,F> : Exclude<T,F> | L : never

Solution by YqxLzx #22192

// your answers // ๅฅฝๅคšไบบ็›ดๆŽฅๆ›ฟๆข T็š„ๅ†…ๅฎน,ไธไผšๆœ‰้—ฎ้ข˜ๅ—? ๆˆ‘้€‰ๆ‹ฉ ๆœ€ๅŽ็ป„ๅˆๆˆT|Rๅ†่ฟ”ๅ›ž.
type UnionReplace<T, U extends [any, any][], R = never>
    = U extends [[infer A, infer B], ... infer C extends [any, any][]]
    ? UnionReplace<T extends A ? never : T, C, R | B>
    : T | R

Solution by goddnsgit #22059

type UnionReplace<T, U extends [any, any][]> = 
  T extends unknown
  ? U extends [[infer SS, infer TT], ...infer Rest extends [any, any][]]
    ? Equal<T, SS> extends true
      ? TT
      : UnionReplace<T, Rest>
    : T
  : never

playground

Key points:

Solution by zhaoyao91 #22041

type UnionInType<T, U extends [any, any][]> = U extends [
  infer A extends [any, any],
  ...infer B extends [any, any][]
]
  ? T extends A[0]
    ? A[1]
    : UnionInType<T, B>
  : T;


type UnionReplace<T, U extends [any, any][]> = T extends T
  ? UnionInType<T, U>
  : never;

Solution by so11y #21337


type UnionReplace<T, U extends [any, any][]> = 
 U extends [infer Start,...infer Other] ?
  Other extends any[]
  ? UnionReplace< ReplaceOne<T,Start> , Other> 
  : never 
   : T

type ReplaceOne<T, U > = U extends [infer Start,infer End] ? T extends Start ? Exclude<T, Start> | End: T: never 

Solution by EGyoung #21212

type Replace<T, U> = U extends [infer Source, infer Target]
  ? Source extends T
    ? Exclude<T, Source> | Target
    : T
  : T;
type UnionReplace<T, U extends [any, any][]> = U extends [infer A, ...infer R]
  ? UnionReplace<Replace<T, A>, R extends [any, any][] ? R : []>
  : T;

Solution by bigcreate #20906

type ReplaceChild<T, S extends [any, any][]> = {
  [K in keyof S]: T extends S[K][0] ? S[K][1] : never;
}[number];

type Replace<
  T,
  S extends [any, any][],
  C = ReplaceChild<T, S>
> = (() => C) extends () => never ? T : C;

type UnionReplace<T, U extends [any, any][]> = T extends any
  ? Replace<T, U>
  : never;

Solution by venusliang #20897

type UnionReplace<T, U extends [any, any][]> = U extends [infer F, ...infer Rest extends [any, any][]]
  ? F extends [T, infer Replace]
    ? UnionReplace<Exclude<T, F[0]> | Replace, Rest>
    : never
  : T

Solution by XkSuperCool #20711

// Exchanges a single type with a match from the array of tuples
// E.g ExchangeType<string, [string, number]> => number
type ExchangeType<T, U extends [any, any][]> = U extends [
  infer H,
  ...infer R extends [any, any][]
]
  ? H extends [infer From, infer To]
    ? T extends From
      ? To
      : ExchangeType<T, R>
    : T
  : T;

type UnionReplace<T, U extends [any, any][]> = T extends T
  ? ExchangeType<T, U>
  : T;

Solution by JohannesSchwegler #20419

type UnionReplace<T, U extends [any, any][]> =
  U extends [infer F, ...infer R extends [any, any][]]
    ? F extends [infer A, infer B]
      ? UnionReplace<Exclude<T, A> | B, R>
      : UnionReplace<T, R>
    : T;

Solution by xiexuan-star #20128