TS(TypeScript) 类型体操: 4518 - Fill 题解

本文介绍如何使用 TypeScript 实现一个类似数组方法 fill 的泛型函数。该函数接受四个参数:目标元组 T、填充值 N 和两个可选参数 Start 与 End,用于指定填充范围。文章详细解析了实现过程中的逻辑思考和技术难点。

Fill

挑战

Fill, a common JavaScript function, now let us implement it with types. Fill<T, N, Start?, End?>, as you can see,Fill accepts four types of parameters, of which T and N are required parameters, and Start and End are optional parameters. The requirements for these parameters are: T must be a tupleN can be any type of value, Start and End must be integers greater than or equal to 0.

type exp = Fill<[1, 2, 3], 0> // expected to be [0, 0, 0]

In order to simulate the real function, the test may contain some boundary conditions, I hope you can enjoy it 😃

解答

解答跟着我的思路一步步来,最后解出最终答案

初始状态:

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
> = any

我们需要用T extends去遍历整个数组

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
> = 
  T extends [infer L,...infer R]
  ? never
  : never

一开始的思路是我们需要有一个 A 元组来传递我们每一步的结果,然后靠A['length']来判断 StartEnd 的边缘状态,大概像下面这样

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  A extends unknown[] = [] 
> = 
  T extends [infer L,...infer R]
   ? A['length'] extends Start
     ? never
     : A['length'] extends End
       ? never
       : never
  : A

但是这样显然不够,因为我们只知道A['length']刚好等于 StartEnd的情况,所以我们需要有一个 booleanIn 来判断我们是否在StartEnd内,如果是在内,那么我们只需要判断End,除此之外,我们只需要判断Start

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  In extends boolean = false,
  A extends unknown[] = [] 
> = 
  T extends [infer L,...infer R]
  ? 
    In extends true 
    ? A['length'] extends End
      ? never
      : never
    : A['length'] extends Start
      ? never
      : never
  : A

然后考虑
在内的时候我们要压入的是N,在外我们要压入L
以及过边缘In的状态转换

就写出了能通过大部分样例的版本

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  In extends boolean = false,
  A extends unknown[] = [] 
> = 
  T extends [infer L,...infer R]
  ? 
    In extends true 
    ? A['length'] extends End
      ? Fill<R,N,Start,End,false,[...A,L]>
      : Fill<R,N,Start,End,true,[...A,N]>
    : A['length'] extends Start
      ? Fill<R,N,Start,End,true,[...A,N]>
      : Fill<R,N,Start,End,false,[...A,L]>
  : A

但是我们发现样例里当StartEnd相等时,是不做替换的

所以加入Start extends End的判断就做出了我们的最终版本:

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  In extends boolean = false,
  A extends unknown[] = [] 
> = 
Start extends End
? T
: T extends [infer L,...infer R]
  ? 
    In extends true 
    ? A['length'] extends End
      ? Fill<R,N,Start,End,false,[...A,L]>
      : Fill<R,N,Start,End,true,[...A,N]>
    : A['length'] extends Start
      ? Fill<R,N,Start,End,true,[...A,N]>
      : Fill<R,N,Start,End,false,[...A,L]>
  : A
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值