类型体操之困难篇题型(第二节)解读

40 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

1. 引言

接下来我们将开启新的篇章继续Ts困难篇的题型练习 https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!

2. 题型

  1. Union to Intersection:实现高级util类型UnionToIntersection
type I = Union2Intersection<'foo' | 42 | true> // expected to be 'foo' & 42 & true

思路:    首先使用类比判断,当入参U 为任意类型时候,判断是否可以作为函数入参,如果可以,使用infer关键字获取到对应回抛参数,抛出值为联合类型。本题结束。 解答:

type UnionToIntersection<U> = (U extends any ? (x:U) => any : never) extends (x:infer A) => any ? A : never

  1. Get Required:实现高级util类型GetRequired,该类型保留所有必填字段
type I = GetRequired<{ foo: number, bar?: string }> // expected to be { foo: number }

思路:    使用映射类型获取对象对应key值后,Required 判断过滤非必填字段后的属性值,如果是必填则保留,非必填移除;本题结束。 解答:

type GetRequired<T> = {
  [P in keyof T as T[P] extends Required<T>[P] ? P : never]: T[P]
}

  1. Get Optional:实现高级util类型GetOptional,该类型保留所有可选字段
type I = GetOptional<{ foo: number, bar?: string }> // expected to be { bar?: string }

思路:    首先定义过滤非必填字段的Required 事件后,使用映射类型后,断言判断当对象值为必选属性时候,过滤掉该键值,否则保留,该题与 Get Required 互为颠倒;解题完成。 解答:


type Required<T> = { [k in keyof T]-?:T[k] }
// type GetRequired<T> = { [k in keyof T as T[k] extends Required<T>[k] ? k : never]:T[k] }
// type GetOptional<T> = { [k in keyof T as k extends keyof GetRequired<T> ? never : k]:T[k] }

type GetOptional<T> = { [k in keyof T as T[k] extends Required<T>[k] ? never : k]:T[k] }