yunliuyan / type-challenges

typescript-challenges
0 stars 2 forks source link

00025-medium-without #25

Open yunliuyan opened 1 year ago

yunliuyan commented 1 year ago

去除数组指定元素 中等 #联合类型 #数组

by Pineapple @Pineapple0919

接受挑战    English

实现一个像 Lodash.without 函数一样的泛型 Without<T, U>,它接收数组类型的 T 和数字或数组类型的 U 为参数,会返回一个去除 U 中元素的数组 T。

例如:

type Res = Without<[1, 2], 1>; // expected to be [2]
type Res1 = Without<[1, 2, 4, 1, 5], [1, 2]>; // expected to be [4, 5]
type Res2 = Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>; // expected to be []

返回首页 分享你的解答 查看解答
yunliuyan commented 1 year ago

思路

借助辅助函数IndexOf

代码实现

type IndexOf<T extends any[], U extends any, Temp extends any[] = []> = T extends [infer F, ...infer O] ? F extends U ? 
Temp['length'] : IndexOf<O, U, [...Temp, F]> : -1 

type WithoutItem<T extends any[], U extends any, Temp extends any[] = []> = T extends [infer F, ...infer O] ? F extends U ? 
WithoutItem<O, U, Temp> : WithoutItem<O, U, [...Temp, F]> : Temp;

type WithoutArr<T extends any[], U extends any[], Temp extends any[] = []> = T extends [infer F, ...infer O] ? IndexOf<U, F> 
extends -1 ? WithoutArr<O, U, [...Temp, F]> : WithoutArr<O, U, Temp> : Temp;

type Without<T extends any[], U extends any> = U extends any[] ? WithoutArr<T, U>  : WithoutItem<T, U>;

type Res = Without<[1, 2], 1>; // expected to be [2]
type Res1 = Without<[1, 2, 4, 1, 5], [1, 2]>; // expected to be [4, 5]
type Res2 = Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>; // expected to be []
Janice-Fan commented 1 year ago
type Union<T extends any | any[]> = T extends any[] ? T[number] : T;
type Without<T extends any[], P extends any | any[]> = 
T extends [infer X, ...infer Y] ? X extends Union<P> ? Without<Y, P> : [X, ...Without<Y, P>] : T;

type Res = Without<[1, 2], 1>; // expected to be [2]
type Res1 = Without<[1, 2, 4, 1, 5], [1, 2]>; // expected to be [4, 5]
type Res2 = Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>; // expected to be []