Trunc
挑战
实现类型版本 Math.trunc
。它接受字符串或数字,删除数字的小数部分返回整数部分。
例如:
type A = Trunc<12.34>; // 12
解答
如果一个数字本身是字符串,那么很容易得到小数点之前的部分。这种方式只是用点分割字 符串得到第一部分。
多亏 Typescript 中的模板字面量类型, 这样做很容易。首先,我们将从需要实现的初始类 型开始:
type Trunc<T> = any;
我们有一个将接受数字本身的类型参数。我们讨论过,通过分割字符串容易得到第一部分, 所以我们需要将数字转换成字符串:
type Trunc<T> = `${T}`;
得到一个报错,“Type ‘T’ is not assignable to type ‘string | number | bigint |
boolean | null | undefined”。为了解决这个问题,我们给类型参数 T
增加一个泛型约
束限制其为数字或字符串:
type Trunc<T extends number | string> = `${T}`;
现在,我们有了数字的字符串表示。接下来,我们可以使用条件类型检查字符串是否带有小 数点。如果有,我们将推断出它们:
type Trunc<T extends number | string> = `${T}` extends `${infer R}.${infer _}`
? never
: never;
有个这个检查,我们可以区分有小数点和没有小数点的情况。
当小数点存在,我们取得小数点前面的部分 R
并返回,忽略小数点后面的部分:
type Trunc<T extends number | string> = `${T}` extends `${infer R}.${infer _}`
? R
: never;
但是如果字符串中没有小数点返回什么呢?它意味着没有什么需要截取,所以我们原样返回 输入类型:
type Trunc<T extends number | string> = `${T}` extends `${infer R}.${infer _}`
? R
: `${T}`;
这样,我们的方案现在通过了所有的测试用例!
评论