实现原理
在 typescript 中可以通过数组的 length 属性读取出值。通过构造数组,进而实现加减乘除。
type A = [1, 2, 3]['length']; // 3
生成数组
目标:通过泛型实现生成指定数组,效果为:type 数组<3> = [1, 1, 1]。
type 生成数组<填充数字 extends number, 数组长度, 已有数组 extends number[]> = 已有数组['length'] extends 数组长度 ? 已有数组 : 生成数组<填充数字, 数组长度, [填充数字, ...已有数组]>
type 数组<数组长度 extends number> = number extends 数组长度 ? 1[] : 生成数组<1, 数组长度, []>
实现加法
type 加法<a extends number, b extends number> = [...数组<a>, ...数组<b>]['length']
实现减法
减法的运算为:差 = 被减数 - 减数,转换为数组则为:差值部分 = 整体部分 - 减去部分,即 整体部分 = 减去部分 + 差值部分(被减数 = 减数 + 差)。
type 减法<a extends number, b extends number> = 数组<a> extends [...减数部分: 数组<b>, ...剩余部分: infer 差值部分] ? 差值部分['length'] : never
实现乘法
乘法的运算为:m + n,转换为数组思路为 n 个长度为 m 的数组相接的新数组的长度。
type _乘法<a extends number, b extends number, pre extends number[]> = b extends 0 ? pre['length'] : _乘法<a, 减法<b, 1>, [...数组<a>, ...pre]>
type 乘法<a extends number, b extends number> = _乘法<a, b, []>
实现除法
除法的运算为:m / n,转换为数组思路为长度为 m 的数组由多少个长度为 n 的数组组成。
type _除法<a extends number, b extends number, pre extends Array<number[]>> = a extends 0 ? pre['length'] : _除法<减法<a, b>, b, [数组<b>, ...pre]>
type 除法<a extends number, b extends number> = _除法<a, b, []>
完整代码
type A = [1, 2, 3]['length']; // 3
type 生成数组<填充数字 extends number, 数组长度, 已有数组 extends number[]> = 已有数组['length'] extends 数组长度 ? 已有数组 : 生成数组<填充数字, 数组长度, [填充数字, ...已有数组]>
type 数组<数组长度 extends number> = number extends 数组长度 ? 1[] : 生成数组<1, 数组长度, []>
type B = 数组<3>
type C = 数组<4>['length']
type 加法<a extends number, b extends number> = [...数组<a>, ...数组<b>]['length']
type D = 加法<3, 4>
type 减法<a extends number, b extends number> = 数组<a> extends [...减数部分: 数组<b>, ...剩余部分: infer 差值部分] ? 差值部分['length'] : never
type E = 减法<4, 3>
type _乘法<a extends number, b extends number, pre extends number[]> = b extends 0 ? pre['length'] : _乘法<a, 减法<b, 1>, [...数组<a>, ...pre]>
type 乘法<a extends number, b extends number> = _乘法<a, b, []>
type F = 乘法<3, 2>
type _除法<a extends number, b extends number, pre extends Array<number[]>> = a extends 0 ? pre['length'] : _除法<减法<a, b>, b, [数组<b>, ...pre]>
type 除法<a extends number, b extends number> = _除法<a, b, []>
type G = 除法<8, 2>