TypeScript 类型系统不是图灵完备,没有数值相关逻辑。对于数值相关的逻辑比较绕。需要数组长度做计数。
TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。
数组长度实现加减乘除
type BuildArray<Length extends number,Ele = unknown,Arr extends unknown[] = []> = Arr['length'] extends Length? Arr: BuildArray<Length, Ele, [...Arr, Ele]>;// Add// 通过 BuildArray 构造两个数组,然后合并成一个,取 lengthtype Add<Num1 extends number, Num2 extends number> =[...BuildArray<Num1>, ...BuildArray<Num2>]['length'];// Subtracttype Subtract<Num1 extends number, Num2 extends number> =BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest]? Rest['length']: never;// Multiply Times// 乘法是多个加法结果的累加,类型参数 ResultArr 保存中间结果,默认值 [],相当于从 0 开始加。// 每加一次就把 Num2 减 1,直到 Num2 为 0,就代表加完type Multip<Num1 extends number,Num2 extends number,ResultArr extends unknown[] = []> = Num2 extends 0 ? ResultArr['length']: Multiply<Num1, Substract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;// Divide// 除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果type Divide<Num1 extends number,Num2 extends number,CountArr extends unknown[] = []> = Num1 extends 0 ? CountArr['length']: Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;
数组长度实现计数
StrLen
数组长度可以取 length 来得到,但字符串类型不能取 length,所以要实现一个求字符串长度的高级类型。
// StrLen// 每次取一个并计数,直到取完,就是字符串的长度type StrLen<Str extends string,CountArr extends unknown[] = []> = Str extends `${string}${infer Rest}`? StrLen<Rest, [...CountArr, unknown]>: CountArr['length'];
GreaterThan
// GreaterThan
type GreaterThan<
Num1 extends number,
Num2 extends number,
CountArr extends unknown[] = []
> = Num1 extends Num2
? false
: CountArr['length'] extends Num2
? true
: CountArr['length'] extends Num1
? false
: GreaterThan<Num1, Num2, [...CountArr, unknown]>;
Fibonacci
// Fibonacci
type FibonacciLoop<
PrevArr extends unknown[],
CurrentArr extends unknown[],
IndexArr extends unknown[] = [],
Number extends number = 1
> = IndexArr['length'] extends Num
? CurrentArr['length']
: FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>
