TypeScript类型体操挑战(二十一)

172 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

中等

IndexOf (Array.indexOf())

挑战要求

在线示例

type IndexOf<T, U, R extends any[] = []> = 
  T extends [infer F, ...infer E]
    ? Equal<F, U> extends true
      ? R['length']
      : IndexOf<E, U, [...R, 0]>
  : -1;



// 使用示例
type Res = IndexOf<[1, 2, 3], 2>; // 1
type Res2 = IndexOf<[0, 0, 0], 2>; // -1
type Res3 = IndexOf<[string, 1, number, 'a', any], any> // 4
  • 我使用了R来存储当前数组迭代的索引
  • Equal就是使用挑战中@type-challenges/utils导入的,用它来进行类型的严格比较,从而判断是否为同一类型
  • T没有值或者迭代完毕,则直接返回-1

Join(Array.join)

挑战要求

在线示例

type Join<T, U extends string | number, R extends string = ''> = 
  T extends [infer F, ...infer E]
    ? Join<E, U, R extends '' ? F : `${R}${U}${F & string}`>
  : R;



// 使用示例
type Res = Join<['Hello', 'World'], ' '>; // 'Hello World'
type Res1 = Join<['2', '2', '2'], 1>; // '21212'
type Res2 = Join<['o'], 'u'>; // 'o'
  • 定义类型R,用来保存拼接好的字符串
  • 然后迭代T,只要有值,就调用Join继续处理下一个元素

核心处理就是对R的处理,其实就是对第一个元素进行判断,因为第一次是不用进行拼接的,直接传递下去即可。

LastIndexOf(Array.lastIndexOf)

挑战要求

在线示例

type LastIndexOf<T, U> = 
  T extends [...infer F, infer E] 
    ? Equal<U, E> extends true
      ? F['length'] 
      : LastIndexOf<F, U> 
  : -1;



// 使用示例
type Res1 = LastIndexOf<[1, 2, 3, 2, 1], 2> // 3
type Res2 = LastIndexOf<[0, 0, 0], 2> // -1
type Res3 = LastIndexOf<[string, any, 1, number, 'a', any, 1], any>	// 5
  • 使用rest 元素就可以轻松地获取到元组最后一个元素
  • 使用挑战中的Equal来严格判断类型是否相等,为true直接返回数组F的长度(此时F的长度相当于T['length'] - 1,刚好对应上当前处理元素的索引)即可,否则继续迭代数组

Unique(lodash.uniq)

挑战要求

在线示例

// 数组 T 中是否包含元素 U
type Include<T, U> = 
  T extends [infer F, ...infer E] 
    ? Equal<F, U> extends true ? true : Include<E, U> 
  : false;

type Unique<T, R extends any[] = []> = 
  T extends [infer F, ...infer E] 
    ? Unique<E, Include<R, F> extends true ? R : [...R, F]> 
  : R;



// 使用示例
type Res = Unique<[1, 1, 2, 2, 3, 3]>; // [1, 2, 3]
type Res4 = Unique<[unknown, unknown, any, any, never, never]>; // [unknown, any, never]
  • Include主要就是用来判断数组T中是否包含元素U,包含返回true,否则返回false

我的解题思路: