数组长度
引入
TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?
BuildArray
中我们使用了 Arr["length"]
是不是就是 数字
所以我们可以通过构造不同的数组然后取 length
的方式来完成数值计算,把数值的加减乘除转化为对数组的提取
和构造
实现加减乘除
Add
实现 10, 10
=> 20
// 我们实现过的 BuildArray
type BuildArray<
Length extends number,
Arr extends unknown[] = [],
> = Arr['length'] extends Length ? Arr : BuildArray<Length, [...Arr, unknown]>;
type Add<Num1 extends number, Num2 extends number> = [
...BuildArray<Num1>,
...BuildArray<Num2>,
]['length'];
type result = Add<20, 20>;
思路
加法就是 数组的合并
, 返回合并后数组的 length
Subtract
type Subtract<
Num1 extends number,
Num2 extends number,
> = BuildArray<Num1> extends [...BuildArray<Num2>, ...infer Rest]
? Rest['length']
: never;
type result = Subtract<20, 10>;
思路
减法就是 数组的拆分
, 返回合并后数组的 length
Multiply
实现 5, 5
=> 25
type Multiply<
Num1 extends number,
Num2 extends number,
Result extends unknown[] = [],
> = Num2 extends 0
? Result['length']
: Multiply<Num1, Subtract<Num2, 1>, [...Result, ...BuildArray<Num1>]>;
type result = Multiply<5, 5>;
思路
乘法 就是 Num2
这么多个 Num1
相加
啥时候结束, 是不是 Num2
变成 0
Divide
实现 10, 5
=> 2
type Divide<
Num1 extends number,
Num2 extends number,
Result extends unknown[] = [],
> = Num1 extends 0
? Result['length']
: Divide<Subtract<Num1, Num2>, Num2, [unknown, ...Result]>;
type result = Divide<10, 5>;
思路
除法 就是 Num1
减去 Num2
的次数, 这个次数 用数组的长度
来表示
啥时候结束, 是不是 Num1
变成 0
数组长度实现计数
StrLen
实现 abc
=> 3
type StrLen<
Str extends string,
Result extends unknown[] = [],
> = Str extends `${infer First}${infer Rest}`
? StrLen<Rest, [unknown, ...Result]>
: Result['length'];
type result = StrLen<'abcde'>;
思路
每取出一个字符 , 就给 result
加一个元素, 最后返回这个 result["length"]
GreaterThan
实现 6, 4
=> true
type GreaterThan<
Num1 extends number,
Num2 extends number,
CountArr extends unknown[] = [],
> = Num1 extends Num2
? false
: CountArr['length'] extends Num1
? false
: CountArr['length'] extends Num2
? true
: GreaterThan<Num1, Num2, [unknown, ...CountArr]>;
type result = GreaterThan<10, 2>;
思路
首先判断 num1
是否能 extends num2
(可能存在相等, 相等就直接返回 false)
这里的 countArr
每次 判断都不会通过 length
都会 加一
, 如果 先到 num1
, 说明 num1
小于 num2
,
先到 num2
说明 num2
小于 num1
Fibonacci
实现 斐波拉契
type FibonacciLoop<
PrevArr extends unknown[],
CurrentArr extends unknown[],
IndexArr extends unknown[] = [],
Num extends number = 1,
> = IndexArr['length'] extends Num
? CurrentArr['length']
: FibonacciLoop<
CurrentArr,
[...PrevArr, ...CurrentArr],
[...IndexArr, unknown],
Num
>;
type Fibonacci<Num extends number> = FibonacciLoop<[unknown], [], [], Num>;
思路
类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。
类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。
类型参数 Num 代表求数列的第几个数。
判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。
否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。
然后继续递归,index + 1,也就是 [...IndexArr, unknown]
总结
TypeScript 类型系统没有加减乘除运算符,所以我们通过数组类型的构造和提取
,然后取长度的方式来实现数值运算