-
Notifications
You must be signed in to change notification settings - Fork 391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
「重学TS 2.0 」TS 练习题第三十三题 #52
Comments
首先利用 TS 模板字符串把默认数组 S 的长度转为字符串,之后那这个字符串和 T 比较,若相等,表示当前 S 的长度和传入的字符串所对应的数值相等 (如,"15" --> 15),否则增加 S 的长度,进行下一次 ToNumber 判断 不过这种方式可能会出现一个警告: 基本上,这种和数组有关系的类型,都需要构建一个辅助数组来进行判断 type ToNumber<T extends string, S extends any[] = [], L extends number = S['length']> =
`${L}` extends T ? L : ToNumber<T, [...S, 1]>
// 用例
type T0 = ToNumber<"0">; // 0
type T1 = ToNumber<"10">; // 10
type T2 = ToNumber<"20">; // 20 |
一个新的思路,感觉有点复杂了,不过比之前的最大限制提升了一些 // 10进制数,递归数不超过10,解决了递归次数过多的报错问题
type GetNumber<T extends any, S extends any[] = [], L extends number = S['length']> =
`${L}` extends T ? L : GetNumber<T, [...S, 1]>
// 字符串转反向数组, 方便从后向前构建目标数组, 如: '1234' -> ['4', '3', '2', '1']
type StrToReverseArr<T extends string> =
T extends `${infer R1}${infer R2}` ? R2 extends '' ? [R1] : [...StrToReverseArr<R2>, R1] : []
/**
* 辅助矩阵, 用于构建当前位数的值, 那上面的 ['4', '3', '2', '1'] 来说, 相当于:
*
* 个位数: 4 --> 构建一个长度为 4*0001 的数组, Matrix<[1], 4>
* 十位数: 3 --> 构建一个长度为 3*0010 的数组, Matrix<Matrix<[1], 10>, 3>
* 百位数: 2 --> 构建一个长度为 2*0100 的数组, Matrix<Matrix<Matrix<[1], 10>, 10>, 2>
* 千位数: 1 --> 构建一个长度为 1*1000 的数组, Matrix<Matrix<Matrix<Matrix<[1], 10>, 10>, 10> , 1>
*/
type Matrix<T extends any[], I extends number> = [
[],
[...T],
[...T, ...T],
[...T, ...T, ...T],
[...T, ...T, ...T, ...T],
[...T, ...T, ...T, ...T, ...T],
[...T, ...T, ...T, ...T, ...T, ...T],
[...T, ...T, ...T, ...T, ...T, ...T, ...T],
[...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T],
[...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T],
[...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T],
][I]
// 生成并合并所有位数的数组
type GetCurArr<
T extends string, // 初始参数, 只在第一次执行时生效, 后面用空字符串 '' 占位
A extends any[] = StrToReverseArr<T>, // 反转后的数组, 只在第一次时通过计算得到, 后面都是递归传入
D extends any[] = [1], // 当前位数的单位长度, 核心是通过这个构建每位所对应的数组, 然后合并他们
> = A extends [infer R1, ...infer R2]
? [...GetCurArr<'', R2, Matrix<D, 10>>, ...Matrix<D, GetNumber<R1>>]
: []
type ToNumber<T extends string> = GetCurArr<T>['length']
// 用例
type T0 = ToNumber<"123">; // 123
type T1 = ToNumber<"10">; // 10
type T2 = ToNumber<"999">; // 999
// type T3 = GetCurArr<"1999">;
// 还是没有完全解决递归的问题, 超过 1000 会报 "Type produces a tuple type that is too large to represent.(2799)" |
type ToNumber<T extends string, A extends any[] = []> = `${A["length"]}` extends T
? A["length"]
: ToNumber<T, [...A, '']>;
type T0 = ToNumber<"0">; // 0
type T1 = ToNumber<"10">; // 10
type T2 = ToNumber<"20">; // 20 思路: ts里运算很匮乏,并没有直接的数字运算,这里巧妙的利用了数组长度来实现,通过递归构造数组,使得构造出来的数组长度和期望的匹配,主要要把数组长度通过字符串模板的方式转换成字符串。否则永远匹配不成功 |
|
// 这个O就算是个数字也可以扩展才对,这就是最佳解法
type ToNumber<T extends string> = T extends `${infer O extends number}` ? O : never
type T0 = ToNumber<"0">; // 0
type T1 = ToNumber<"10">; // 10
type T2 = ToNumber<"20">; // 20 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
实现一个
ToNumber
工具类型,用于实现把数值字符串类型转换为数值类型。具体的使用示例如下所示:The text was updated successfully, but these errors were encountered: