00399-hard-tuple-filter

Back

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

Solution by Talljack #32704

type FilterOut<T extends any[], F> = T extends [infer L, ...infer R]
  ? [L] extends [F]
    ? FilterOut<R, F>
    : [L, ...FilterOut<R, F>]
  : [];


Solution by Vampirelee #32621

type FilterOut<T extends any[], F> = T extends [infer L, ...infer R]
  ? [L] extends [F]
    ? FilterOut<R, F>
    : [L, ...FilterOut<R, F>]
  : T;

Solution by vangie #32254

type FilterOut<T extends any[], F> = T extends [infer A, ...infer B] ? [A] extends [F] ? [...FilterOut<B, F>] : [A, ...FilterOut<B, F>] : []

Solution by dreamluo-plus #30265

type FilterOut<T extends any[], S> 
= T extends [infer First, ...infer Rest] ?
 (S extends First ? (First extends S ? FilterOut<Rest, S>
 : [First, ...FilterOut<Rest, S>])
 : [First, ...FilterOut<Rest, S>]) : []

Solution by Lwenkun #29898

type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends (<G>() => G extends B ? 1 : 2) ? true : false

type FilterOut<T extends any[], F, Result extends any[] = []> = T extends [infer L, ...infer R] 
  ? [L] extends [F] 
    ? FilterOut<R, F, Result> 
    : FilterOut<R, F, [...Result, L]> 
  : Result

Solution by dmytro-shumak #29292

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

Solution by de-novo #27817

type FilterOut<T extends any[], F, U extends any[] = []> =
  T extends [infer C, ...infer R] ? FilterOut<R, F, [...U, ...([C] extends [F] ? [] : [C])]> : U

Solution by smileboyi #27442

// your answers

type MyInclude<T, V, U = T> = 
  T extends U
    ? Equal<T, V> extends true
      ? true
      : never
    : never

type FilterOut<T extends any[], V, R extends any[] = []> =
  T extends [infer F, ...infer Rest]
    ? [F] extends [never]
      ? FilterOut<Rest, V, R>
      : Equal<MyInclude<V, F>, true> extends true
        ? FilterOut<Rest, V, R>
        : FilterOut<Rest, V, [...R, F]>
    : R

Solution by enochjs #26782

This is my first version answer

type FilterOut<T extends any[], F, Res extends any[] = []> = 
  T extends [infer X, ...infer Y]
  ? X extends F
    ? FilterOut<Y, F, Res>
    : FilterOut<Y, F, [...Res, X]>
  : Res

We can easily have this idea, recursively process each item in the array T, and then make judgments separately.
This can be work in some examples like FilterOut<['a', 'b'], 'c'>. However, this method has some bad cases

  1. union type: For FilterOut<['a', number | string], number>, we want to get ['a', string | number]. However, we get ['a'] | ['a', string] as the final result.
  2. never: For FilterOut<['a', never], never>, we get straight to never! Not only we have no way to get ['a'], we even have no way to get an array as a return type.

This code can fix all bad cases. We just modify X extends F to [X] extends [F]

type FilterOut<T extends any[], F, Res extends any[] = []> = 
  T extends [infer X, ...infer Y]
  ? [X] extends [F]
    ? FilterOut<Y, F, Res>
    : FilterOut<Y, F, [...Res, X]>
  : Res

But why did the above two problems happen?

The first union type problem is very easy to understand, because it triggers the distributed processing of the union type

But the second never problem is very strange. In fact, if you try more operations related to never, you will find a lot of strange phenomena, such as

type t3 = never extends never ? 1 : 2 // 1 -> Correct
type test<T, F> =
  T extends F 
    ? 1
    : 2 

type t4 = test<never, never> // never -> Wrong, we expect to get 1

The essential reason is that when never is passed in as the parameter T of test, it will be regarded as an empty union by the compiler, and this is still a union type, which triggers the distributed processing of the union type, and returns an empty union as a result union (that is, never)

Solution by kiki-zjq #26112

type FilterOut<T extends any[], F> = T extends [infer Head, ...infer Tail] ? [Head] extends [F] ? FilterOut<Tail, F> : [Head, ...FilterOut<Tail, F>] : [];

Solution by guckin #25462

type FilterOut<T extends any[], F> = T extends [infer Fst, ...infer R] ? ([Fst] extends [F] ? FilterOut<R, F> : [Fst, ...FilterOut<R, F>]) : [];

Solution by E-uler #24771

// your answers
type FilterOut<T extends any[], F,R extends any[] = []> = T extends [infer First,...infer O] 
? [First] extends [F] ?FilterOut<O,F,R>:FilterOut<O,F,[...R,First]>
:R

Solution by walker-hzx #24605

type FilterOut<T extends any[], F> = T extends [infer First, ...infer Rest]
? [First] extends [F]
  ? FilterOut<Rest, F>
  : [First, ...FilterOut<Rest, F>]
: T

Solution by NeylonR #24447

// your answers
type FilterOut<T extends any[], F, Acc extends any[] = []> = T extends [infer A, ...infer R] ? 
[A] extends [F] ? FilterOut<R, F, Acc> : FilterOut<R, F, [...Acc, A]> : Acc

Solution by snakeUni #23586

// your answers
type FilterOut<T extends any[], F> = T extends [infer First, ...infer Rest]
	? [First] extends [F]
		? [...FilterOut<Rest, F>]
		: [First, ...FilterOut<Rest, F>]
	: T

Solution by jxhhdx #22945

type FilterOut<T extends any[], F> = T extends [infer First, ...infer Rest]
	? [First] extends [F]
		? [...FilterOut<Rest, F>]
		: [First, ...FilterOut<Rest, F>]
	: T

Solution by TKBnice #22858

type FilterOut<T extends unknown[], P> =
  T extends [infer A, ...infer Rest]
    ? [...([A] extends [P] ? [] : [A]), ...FilterOut<Rest, P>]
    : []

Solution by drylint #22226

type FilterOut<T extends unknown[], F> = T extends [infer S, ...infer Rest] ?
 [...([S] extends [F] ? [] : [S]), ...FilterOut<Rest, F>]: [];

Solution by Karamuto #21995

type FilterOut<T extends any[], F> = 
  T extends [infer X, ...infer R]
    ? [...([X] extends [F] ? [] : [X]), ...FilterOut<R, F>]
    : []

Solution by ivbrajkovic #21642

// your answers
type FilterOut<T extends any[], F, Pre extends any[] = []> = T extends [
  infer k,
  ...infer Rest
]
  ? FilterOut<Rest, F, [k] extends [F] ? Pre : [...Pre, k]>
  : Pre

Solution by wangxdmm #21102

// your answers
type FilterOut<T extends any[], F,S extends any[] = []> = S extends [...infer G] ?  T extends [infer First,...infer Rest] ? [First] extends [F] ? FilterOut<Rest,F,G> : FilterOut<Rest,F,[...G,First]> : S : S

Solution by YqxLzx #20916

// your answers
// 1. 当 与 F ε…¨η­‰οΌŒζˆ–θ€…ζ˜―ε±žδΊŽ F ηš„ε­ι›†ιƒ½θ¦θΏ‡ζ»€ζŽ‰
type FilterOut<T extends any[], F, Ret extends any[] = []> = T extends [infer First, ... infer Rest] ? Equal<First, F> extends true ? FilterOut<Rest, F, Ret> : [First] extends [F] ? FilterOut<Rest, F, Ret> : FilterOut<Rest, F, [...Ret, First]> : Ret

Solution by Rebornjiang #20598

type FilterOut<T extends any[], F> = 
  T extends [infer A, ...infer Rest]
    ? [A] extends [F]
      ? FilterOut<Rest, F>
      : [A, ...FilterOut<Rest, F>]
    : T

Solution by zhaoyao91 #20492

type UnionToFnInsertion<T> =
  (T extends any ? (arg: () => T) => any : never) extends (arg: infer P) => any
    ? P : never

type UnionToTuple<T> = UnionToFnInsertion<T> extends () => infer R
  ? [R, ...UnionToTuple<Exclude<T, R | never>> ]
  : never extends T ? [never] : []

type InTuple<T extends any[], U> = T extends [infer F, ...infer O]
  ? Equal<F, U> extends true ? true : InTuple<O, U>
  : false


type FilterOut<T extends any[], F, R extends any[] = []> = T extends [infer L, ...infer O]
  ? InTuple<UnionToTuple<F>, L> extends true
    ? FilterOut<O, F, R>
    : FilterOut<O, F, [...R, L]>
  : R

Solution by pengzhanbo #20478

// your answers
type FilterOut<T, A> = T extends [infer F, ...infer L]
  ? F extends A
    ? FilterOut<L, A>
    : [F, ...FilterOut<L, A>]
  : [];

Solution by fengjinlong #20241

type FilterOut<T extends any[], F, Result extends any[] = []> = T extends [infer A, ...infer R] ? [A] extends [F] ? FilterOut<R, F, Result> : FilterOut<R, F, [...Result, A]> : Result

Solution by sromic #19085

type FilterOut<T extends any[], F, Total extends unknown[] = []> =
 T extends [infer F1, ...infer R1] 
 ? ([F1] extends [F] 
  ? FilterOut<R1, F, Total> 
  : FilterOut<R1, F, [...Total, F1]>) 
 : Total;

Solution by CaoXueLiang #19037

type FilterOut<T extends any[], F> = T extends [infer L, ...infer R]
  ? [L] extends [F]
    ? FilterOut<R, F>
    : [L, ...FilterOut<R, F>]
  : []

Solution by milletlovemouse #18897

// your answers
type SelfEqual<T, R> = (<K>(T) => K extends T ? 1 : 2) extends (<K>(T) => K extends R ? 1 : 2) 
                                                        ? true 
                                                        : [T] extends [R]
                                                                ? true
                                                                : false;

type FilterOut<T extends any[], F, Result extends any[] = []> = T extends [infer R, ...infer U]
                                                                    ? SelfEqual<R, F> extends true
                                                                        ? FilterOut<U, F, Result>
                                                                        : FilterOut<U, F, [...Result, R]>
                                                                    : Result;

Solution by jiaaoMario #17398