TS与数组的那些事儿😏

引言

TS 是 JavaScript 的超集!那 TS 可以实现类似数组的方法吗?今天我们就来探索 TS 那些有趣的玩法!

pop、push、shift、unshift

下面我们会用到一些 TS 高级语法,有不懂的可以先去看 TS 文档传送门。让我们先从简单的着手~

pop

js 复制代码
    type Pop<T extends any[]> = T extends [...infer F, L] ? L : never
    
    // 让我们测试一下
    type p1 = Pop<[1,2,3,4,5]> // 5
    type p2 = Pop<['hello']> // hello

这儿用到了 extends(TS2.8版本) 语法、infer(TS2.8版本) 语法、...(TS3.0版本)语法,后面会大量用到,不懂得可以先去做了解。

push

js 复制代码
    type Push<T extends any[], V> = V extends any[] ? [...T, ...V] : [...T, V]
    
    type p2 = Push<[1,2,3,4,5], ['hello', 'world']> // [1,2,3,4,5,hello,world]
    type p2 = Push<[1,2,3,4,5], ['hello', ['world']]> // [1,2,3,4,5,hello,[world]]
    type p4 = Push<[1,2,3,4], 5> // [1,2,3,4,5]

是不是 so easy! :)下面我们提高难度

shift、unshift 方法类似,大家可以自行尝试

reverse、flat、filter、splice、join

reverse(反转

js 复制代码
    type Reverse<T extends any[], R extends any[] = []> = T extends [infer F, ...infer L] ? Reverse<L, [F, ...R]> : R
    
    type r1 = Reverse<[1,2,3,4,5> // [5,4,3,2,1]

我们采用递归思想(下面基本都会用到递归,同学们食好瓜子er),先取出第一个值,然后递归放入我们的结果数组中,注意最后[F, ...R],别放反了!

flat(拍平,一马平川

js 复制代码
    type Flat<T extends any[]> = T extends [infer F, ...infer S] ? [...(F extends any[] ? Flat<F> : [F]), ...Flat<S>] : T
    
    type f1 = Flat<[[[4]]], 5]> // [4, 5]

没办法,继续递归~

filter(过滤

做之前仔细想一下,这里面是要作比较,判断两个类型是否一致,一致就过滤出来。那我们怎么判断呢?

js 复制代码
    // 这段代码有点啰嗦,各位同学可以试着精简一下
    type Filter<
        T extends any[],
        V,
        R extends any[] = []
        > = T extends [infer F, ...infer S]
                ? F extends V
                    ? Filter<S, V, [...R, F]>
                : Filter<S, V, R>
            : R
    
    type f1 = Filter<[1, 'bef', 2, any, 'dev'], string> // ['bef', any, 'dev'] | ['bef', 'dev']

我们发现上面的代码,产生了两种结果,这是为什么?(别问我,我也木鸡啊:)

其实这是 TS 类型分发问题,原理很简单,举个栗子

type a = any extends string ? 1 : 2,你会发现结果是联合类型 1 | 2,仔细想下很简单,any可以是任何东西,可以是 number,可以是 string ,那 number 是 string 类型吗?显然不是,返回 2 ,那 string 是 string 类型吗?显然是,返回 1 ,一联合就是 1 | 2。 原理我们知道了,怎么规避呢?在了解了什么情况下会产生类型分发,就很好解决了。只要它不是裸类型 (当然,字面量 作比较,是不会分发的),就不会分发了,我们可以在 F extends V 包一层,[F] extends [V] 就OK了

splice(删除、追加、替换

js 复制代码
type Splice<
    T extends any[],
    S extends number, // 开始删除的索引
    C extends number = T['length'], // 删除的个数
    IN extends any[] = [], // 需要替换的值
    SA extends any[] = [], // 用于计算开始的位置
    EA extends any[] = [], // 用于计算删除的个数
    F extends any[] = [] // 前面需要保留的值
    > = T extends [infer L, ...infer R]
            ? SA['length'] extends S
                ? EA['length'] extends C
                    ? [...F, ...IN, L, ...R] // [...F, ...IN, ...T]
                : Splice<R, S, C, IN, SA, [...EA, never], F>
            : Splice<R, S, C, IN, [...SA, never], EA, [...F, L]>
        : [...F, ...IN]

type a1 = Splice<[boolean, 1, 'a', never, string], 1, 2, [3, 3]> // [boolean, 3, 3, never, string]
type a2 = Splice<[boolean, 'never', 1, 2, string], 0> // []
type a3 = Splice<[boolean, any, number, 2, 'a'], 1, 1> // [boolean, number, 2, 'a']
type a4 = Splice<[boolean, any, number, 2, 'a'], 4, 0, [99]> // [boolean, any, number, 2, 99, 'a']

注意看第二个栗子(a2),删除的个数,默认删除开始位置到数组最后一项。在最后的结果中,须将当前的 L 放进去(就因为这个点,当初迷惑了我一下午:)

join(拼接

js 复制代码
type Join<
    T extends any[],
    R extends string = ''
    > = T extends [infer F, ...infer S]
            ? S['length'] extends 0
                ? `${R}${F}`
            : Join<S, `${R}${F}`>
        : ''

type s = Join<['h', 'e', 'l', 'l', 'o']> // hello

总结

上面介绍了 TS 与数组的不解之缘,可谓有趣的很。还有很多有趣的玩法,这里就不一一列举了。除了数组,还有字符串。有时间可以跟大家一起探讨~

相关推荐
天下无贼!6 小时前
2024年最新版TypeScript学习笔记——泛型、接口、枚举、自定义类型等知识点
前端·javascript·vue.js·笔记·学习·typescript·html
Jorah2 天前
1. TypeScript基本语法
javascript·ubuntu·typescript
小白小白从不日白3 天前
TS axios封装
前端·typescript
aimmon4 天前
Superset二次开发之源码DependencyList.tsx 分析
前端·typescript·二次开发·bi·superset
下雪天的夏风4 天前
Vant 按需引入导致 Typescript,eslint 报错问题
前端·typescript·eslint
theMuseCatcher5 天前
Vue3+TypeScript+Vite+Less 开发 H5 项目(amfe-flexible + postcss-pxtorem)
typescript·less·postcss
Qiyandays5 天前
vue + Lodop 制作可视化设计页面 实现打印设计功能(四)
前端·vue.js·typescript
人工智能的苟富贵5 天前
微信小程序中的模块化、组件化开发:完整指南
微信小程序·小程序·typescript
Code blocks7 天前
小试牛刀-区块链Solana多签账户
算法·typescript·区块链·github
shiming88797 天前
Vue 生命周期与 TypeScript:深入理解组件生命周期
前端·vue.js·typescript