typescript 类型体操 之 529-medium-absolute

360 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

前言

在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,在之前篇文章中,我们完成了中等的第二十题,今天来做中等的第二十一题 529-medium-absolute

下面这个是类型体操github仓库:

type-challenges/type-challenges: Collection of TypeScript type challenges with online judge (github.com)

529-medium-absolute

image.png

import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Absolute<0>, '0'>>,
  Expect<Equal<Absolute<-0>, '0'>>,
  Expect<Equal<Absolute<10>, '10'>>,
  Expect<Equal<Absolute<-5>, '5'>>,
  Expect<Equal<Absolute<'0'>, '0'>>,
  Expect<Equal<Absolute<'-0'>, '0'>>,
  Expect<Equal<Absolute<'10'>, '10'>>,
  Expect<Equal<Absolute<'-5'>, '5'>>,
  Expect<Equal<Absolute<-1_000_000n>, '1000000'>>,
  Expect<Equal<Absolute<9_999n>, '9999'>>,
]

从README和测试用例中能够得出,我们需要实现一个工具函数 Absolute 能够将字符串,数字或者 bigint 取绝对值。

利用 JS 进行模拟学习

利用 JS 取绝对值最简单的方法是通过 Math 的内置方法 Math.abs()

function absolute(val:any){
    return Math.abs(val)
}

image.png

又或者可以把值转化为字符串,然后对字符串进行判断处理

function absolute2(val:any){
    let str = val.toString()
    let newStr = ''
    for(const ch of str){
        if(ch != '-'){
            newStr+=ch
        }
    }
    return newStr
}

image.png

实现 Absolute

对于 TS 来说就没有那么多内置工具,所以我们采用第二种方式,将三种类型都统一转为字符串然后在做出处理。

因为对于负数来说,有负号的话也一定会是在第一个字符上,所以我们只需要对转化后的字符串的第一个字符做出判断,看看它是否是 - 字面量,是的话就说明这个数是一个负数,需要去掉第一个符号,不是的话就直接返回。

image.png

值得注意的一个点是,测试用例中,无论是数字还是字符串,最后返回的都是字符串字面量,那么就是说我们对于入参还需要做出一层字符串字面量的包装。

type Absolute<T extends number | string | bigint> =
    `${T}` extends `${infer S}${infer R}`
        ? S extends `-`
            ? `${R}`
            : `${T}`
        : never;

这样我们的测试case就能够全部通过了。

知识点

关于上述提到了部分的知识点:

  1. 字符串字面量
  2. 条件链

今天的题目使用的都是旧的知识点,解题方式也是碰过很多次的了,在这里就不做过多描述。

总结

今天我们做完了中等的第二十一题,题目比较简单,属于之前很经常碰到的字符串字面量特殊处理的题目,在我们碰到数字类型不好进行处理的时候,可以考虑将它转化为字符串字面量在进行处理,这是一个比较不错的方法。