Ts类型体操Easy部分

简介: Ts类型体操Easy部分

手把手一起完成Ts类型体操中的Easy部分


我们可以先了解一下类型体操的分类

  • 对属性的修饰,包括对象属性和数组元素的可选/必选、只读/可写。我们将这一类统称为属性修饰工具类型
  • 对既有类型的裁剪、拼接、转换等,比如使用对一个对象类型裁剪得到一个新的对象类型,将联合类型结构转换到交叉类型结构。我们将这一类统称为结构工具类型
  • 对集合(即联合类型)的处理,即交集、并集、差集、补集。我们将这一类统称为集合工具类型
  • 基于 infer 的模式匹配,即对一个既有类型特定位置类型的提取,比如提取函数类型签名中的返回值类型。我们将其统称为模式匹配工具类型
  • 模板字符串专属的工具类型,比如神奇地将一个对象类型中的所有属性名转换为大驼峰的形式。这一类当然就统称为模板字符串工具类型了。


实现Pick




type MyPick<T, K> = any

Pick<Type, Keys>用于构造一个类型,它是从Type类型里面挑了一些属性Keys(Keys是字符串字面量 或者 字符串字面量的联合类型), 所以Pick返回的是一个对象。

改写第一步

type MyPick<T, K> = {
}

我们可以从遍历K中的属性名,然后从T中取出相应的类型

image.png

但是现在还是报错的,并且测试用例也没有通过,原因是 T 中可能不存在 K中的相应类型

举个例子, 这时候Todo里面没有 'lesson' 属性,不就报错了吗!,所以我们需要用extends约束一下 K 的类型


interface Todo {
    title: string
    description: string
    completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'| 'lesson'>

答案


type MyPick<T, K extends keyof T> = {
  [Key in K ]: T[Key]
}


实现Readonly



直接遍历T中的属性,然后加上readonly关键字就好了


type MyReadonly<T> = {
  readonly [key in keyof T] :T[key]
}


元组转换为对象



怎么从元组里面拿到所有的类型

Tuple[number]  // 可以获得元组所有类型的组合


type TupleToObject<T extends readonly any[]> = {
  [key in T[number]] : key
}


第一个元素


使用infer关键字,占取第一个元素,并将剩余元素收集起来。 根据测试用例的提示,当数组为空时,返回的是never类型


type First<T extends any[]> = T extends [infer one, ... any[]] ? one : never


获取元素长度



我们可以通过length属性,直接返回元素的长度


type Length<T> = T['length']

但是我们必须要对 T 进行进一步的约束,确保 T 中有length属性


type Length<T extends any[]> = T['length']

但是这时候我们还是报错,说readonly和any[]不匹配,我们要在前面加上readonly即可

image.png


type Length<T extends  readonly any[]> = T['length']


Exclude



前置知识,分发条件类型(Distributive Conditional Types)

当在泛型中使用条件类型时,如果传入的是一个联合类型,就会变成分发的 。相当于会自动一个个遍历进行判断


type StrArrOrNumArr = ToArray<string | number>;        
// type StrArrOrNumArr = string[] | number[]

了解了这些,我们就可以来实现Exclude了

因为T是联合类型,会自动遍历里面的属性, 当 T 中的属性存在于 U 时,就返回never ,否则返回遍历到的当前类型


type MyExclude<T, U> = T extends U ? never: T


Awaited



学习TypeScript28(infer 递归)_小满zs的博客-CSDN博客)


type MyAwaited<T> = T extends PromiseLike<infer K> ? MyAwaited<K> : T;

If



非常简单,不多解释


type If<C, T, F> = C  extends true ? T :F

Concat



直接用收集展开处理

type Concat<T, U> = [...T ,...U]

但是这时候却报错了,因为ts并不知道T,U是一个元组

image.png

用extends进行类型约束


type Concat<T extends any[], U extends any[]> = [...T ,...U]

Includes



思路很简单,依次遍历T里面有没有U这个属性,有的话就是true,否则返回false

来看代码怎么实现,先对比第一个,再递归对比剩余的


type Includes<T extends readonly any[], U> = T extends [infer one ,... infer rest]? 
one extends U ? true: Includes<rest,U>:
false

但是我们发现测试用例并没有全部通过

image.png我们在判断相等的时候,使用的extends。 但是false是 boolean的子集 ,返回的是true。但是我们想进行严格判断返回false,我们可以使用它提供的Equal函数(偷懒.png)


type Includes<T extends readonly any[], U> = T extends [infer one ,... infer rest]? 
Equal<one ,U> extends true ? true: Includes<rest,U>:
false

Push



同理


type Push<T extends any[], U> = [...T ,U]

Unshift




type Unshift<T  extends any[], U> = [U, ...T]

Parameters



把函数的参数收集起来,然后直接返回就好了


type MyParameters<T extends (...args: any[]) => any> = T extends (...rest:infer P) => any ? P : undefined



目录
相关文章
|
7月前
|
JavaScript Java 编译器
TS的重新学习(二)
TS的重新学习(二)
29 0
|
7月前
|
Java 编译器
TS的重新学习(三)
TS的重新学习(三)
24 0
|
4月前
|
存储 JavaScript 前端开发
成为优秀的TS体操高手 之 TS 类型体操前置知识储备
成为优秀的TS体操高手 之 TS 类型体操前置知识储备
|
7月前
|
JavaScript 前端开发 Java
对TS的重新学习(一)
对TS的重新学习(一)
24 0
|
7月前
|
存储 JavaScript Java
TS的重新学习(四)
TS的重新学习(四)
30 0
|
9月前
|
JavaScript 前端开发
TS基础用法
TS基础用法
65 0
|
JavaScript
TS类型推论
TS类型推论
68 0
|
JavaScript
记录下最近泛型(ts)的使用心得
软件设计中规范和灵活往往是相悖的,约束越多规范性越强反之灵活性越低。一款优秀的软件系统在这两者之间把握的一定很好。对于typescript而言,他给js上上了一道类型的加锁,如果说any是打开这把锁的钥匙那泛型同时也给了js类型一定的自主空间,就是我们常用的泛型。
|
JavaScript 前端开发 安全
TS学习(一):基础使用
TS学习(一):基础使用
TS学习(一):基础使用
ts重点学习28-bigint和symbol笔记
ts重点学习28-bigint和symbol笔记
124 0