TypeScript类型体操姿势合集-easy题解

6 篇文章 0 订阅
4 篇文章 0 订阅

TypeScript类型体操,核心思想是 通过类型生成新的类型!

记录一下type-challenges的简单题题解,以及解题思路。

仓库地址:https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md

博文地址:https://github.com/FrankKai/FrankKai.github.io/issues/262

4 - 实现 Pick

keyof / extends / in

type MyPick<T, K extends keyof T> = { [P in K] : T[P]}
解题思路

其中的<T, K extends keyof T>:K是公共类型,意思是K类型是 keyof T结果的子集。这样做能保证Pick的第二个参数的类型,不在第一个参数的类型,会提示报错

比如,下面代码传了一个在Todo类型上不存在的’invalid’,ts会提示报错” Type ‘“invalid”’ is not assignable to type ‘keyof Todo’.“

// @ts-expect-error
type newType = MyPick<Todo, 'title' | 'completed' | 'invalid'>

interface Todo {
  title: string
  description: string
  completed: boolean
}

https://github.com/type-challenges/type-challenges/issues/11021

7 - 实现 Readonly

readonly

type MyReadonly<T> = { readonly [P in keyof T] : T[P] }
解题思路

在属性名前增加readonly,即可实现只读。

key部分:利用keyof T得到T的键集合,再利用P in 做遍历,并为每个属性名增加readonly标识。

value部分:T[P],复用原先的类型即可。

https://github.com/type-challenges/type-challenges/issues/11104

11 - 元组转换为对象

extends / readonly / in / T[number]

type TupleToObject<T extends readonly any[]> = { [P in T[number]: P }
解题思路

重点是“如何遍历元祖中的每一项?”,可以通过number索引,也就是T[number]获取到每一项。

为什么要T extends readonly any[],这是因为要传入的是一个任意类型的数组,而T[]这种事不合法的,所以需要使用extends去构造一个新的类型。

https://github.com/type-challenges/type-challenges/issues/11105

14 - 第一个元素

extends / never / T[0]

type First<T extends any[]> = T extends [] ? never : T[0];
解析思路

第一项通过T[0]即可表示。

有一个用例需要注意:空数组时,第一项表示为never。

重点是 如何判断空数组?有2种办法:T extends []T["length"] extends 0

https://github.com/type-challenges/type-challenges/issues/11107

18 - 获取元组长度

extends / readonly / T['length']

type Length<T extends readonly any[]> = T['length']
解题思路

可以通过T[‘length’]返回长度。

但是前提是构造一个新的类型,T extends any[]

由于元组类型是只读的,所以需要T extends readonly any[]

11.元组转对象思路一致

https://github.com/type-challenges/type-challenges/issues/11109

43 - Exclude

extends / never

type MyExclude<T, U> = T extends U ? never : T
解题思路

重点是如何移除U,T中的某一项如果在U中(T extends U),返回never移除U,否则返回T。

https://github.com/type-challenges/type-challenges/issues/11111

189 - Awaited #11747

infer / 递归 / Promise<T>

type MyAwaited<T> = T extends Promise<infer P> 
  ? P extends Promise<any>
    ? MyAwaited<P>
    : P
  : never;
解题思路

infer + 递归 + Promise

对于普通的类型,例如type X = Promise,用T extends Promise 即可判断出。
但是对于嵌套类型,例如type Z = Promise<Promise<string | number>>,需要再判断一下P是否为Promise类型,若是的话,递归判断。

https://github.com/type-challenges/type-challenges/issues/11747

268 - If

extends boolean / extends true

if<C extends boolean, T, F> = C extends true ? T : F
解题思路

如何约束泛型为boolean类型?C extends boolean。

如何判断当前泛型为true?C extends true。

https://github.com/type-challenges/type-challenges/issues/11404

533 - Concat

...T 解构

type Contact<T extends any[], U extends any[]> = [...T, ...U]
解题思路

数组类型入参:T extends any[]

泛型解构(核心:通过…解构泛型变量):[…T, …U]

https://github.com/type-challenges/type-challenges/issues/11423

898 - Includes

infer / ...T 解构 / 递归

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

type Includes<T extends readonly any[], U> = T extends [infer P, ...infer Rest] 
  ? MyEqual<P, U> extends true 
    ? true
    : Includes<Rest, U>
  : false;
解题思路

解构+infer+递归

判断方式:递归取T中第一项与U进行判断是否相等。

需要实现一个Equal函数,可以使用官方讨论中的https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650

https://github.com/type-challenges/type-challenges/issues/11534

3057 - Push

...T 解构

type Push<T extends any[], U> = [...T, U]
解题思路

约束数组类型变量:T extends any[]

类型变量解构: …T

https://github.com/type-challenges/type-challenges/issues/11527

3060 - Unshift

...T 解构

type Unshift<T extends any[], U> = [U, ...T]
解题思路

约束数组类型变量:T extends any[]

类型变量解构: …T

https://github.com/type-challenges/type-challenges/issues/11529

3312 - Parameters

infer

type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer P) => unknown ? P : never;
解题思路

使用infer表示待推断的类型变量。

由于…args本身已经是元组类型,因此infer P最终推导出的,也是元组类型。

https://github.com/type-challenges/type-challenges/issues/11539

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值