Typescript的体操入门---02

138 阅读3分钟

这是一个系列的主要是针对Typescript的体操入门,实际题目都是来自于type-challenges,后面可能也会穿插一些拆分出来的思考习题(也欢迎大家提出一些有意思的题去一块学习),这里会大概以每周1题(前面很多简单题会快一些)的顺序去带着大家一起去练习和讲解。我个人也是去年才开始学习和使用Typescript,在中间存在任何概念或者描述错误的也希望大家直接指出来,共同进步。


习题入口

目标就是属性变为readobly

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

很简答的题 主要是改变属性只读 这里其实还隐藏了一个符号+ 完整的代码是

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

那当我们需要去除的时候 就是用 -


习题入口

元祖转对象

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

这里有两个点 第一个点就是因为key需要当做属性 所以这里需要对于value做类型约束 第二个就是数组获取value的联合 直接[number]就可以得到


习题入口

获取第一个元素

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

一个很基本的泛型 在泛型的三目中 泛型参数只能在他的三目的真值中使用


习题入口

获取数组长度

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

获取数组长度 这个一般在后面使用会比较多 做一些number的判断


习题入口

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

naked type 在extends会分发 只有never的时候会直接返回never

type demo<T> = T extends 1 ? 1 : 2

type isNever = demo<never> // 这里会返回never

简单理解就是一个不可达的类型进来无论判断是什么他都不会往后走


习题入口

type MyAwaited<T extends Promise<any>> = T extends Promise<infer P> ? P extends Promise<any> ? MyAwaited<P> : P : never

我写的时候还没这道题 其实写体操主要还是你思路流程有没有 你有了思路那就是ts能不能实现,基本这两种都有不错的积累,就能满足绝大多数场景

实际思路就是是不是Promise<any>的结构继续取,不是直接返回。


习题入口

type If<C extends boolean, T, F> = [C] extends [true] ? T : [C] extends [false] ? F : never

我这里使用数组包裹是防止他是一个naked type


习题入口

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

这个和js就没差别了


习题入口

判断一个元素存在在数组中吗

type Includes<T extends readonly any[], U> = T extends [infer F,...infer Rest] ? [U, F] extends [F, U] ? true : Includes<Rest, U> : false;

我的最开始实现是上面的 然后看到了只读属性区分... 这里其实有个需要你背下来的方法Equal

type Equal<X, Y> = <T>() => T extends X ? 1 : 2 extends <T>() => T extends Y ? 1 : 2 ? true : false

我觉得这个API完全ts可以内置下可以看下别人的解释地址

不过我还是不是很理解- -~

所以可以实现成

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

习题入口

模拟数组的push和Unshift都写在下面了 因为确实没啥难度

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

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

习题入口

返回函数参数

type MyParameters<T extends (...args: any[]) => any> = T extends (...parameters: infer P) => void ? P : never

泛型取一下


到这里可以看到easy都是一些最基本的单个操作就可以完成的逻辑,这里更多是在普及后面需要用的方法和他会产生什么结果 下面的M也不会绝大多数也不会很难 很多都很类似,今天先到这里,可以多去试一试 看看这几个基本操作都会返回什么。

别人测试的类型图 地址