TypeScript类型体操挑战(十三)

511 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

中等

RequiredByKeys

挑战要求

在线示例

type RequiredByKeys<T, K = keyof T, U extends keyof T = keyof T> =
  Omit<Required<Pick<T, K & U>> & Omit<T, K & U>, never>;

道理跟PartialByKeys是一样的,可以看我上一篇文章

  • Required<Pick<T, K & U>>用于从T中获取键K类型的字段组成新对象,并且将该对象的属性都设为必须的
  • Omit<T, K & U>, never>用于从T中获取键不为K类型的字段组成新对象
  • 最后再使用Omit将上面两个对象组合成一个完整的新对象,就达到目的了

Mutable

挑战要求

在线示例

type Mutable<T extends Record<PropertyKey, any>> = {
  -readonly [P in keyof T]: T[P] extends object ? Mutable<T[P]> : T[P];
}
  1. 使用T extends Record<PropertyKey, any>可以约束传入的参数是一个对象或数组。

PropertyKey是一个内置工具类型,代表了有效的键的类型:

type PropertyKey = string | number | symbol

数组的话,可以使用数字索引进行访问,所以这个类型是可以很好地检查出传入的参数是否为{}组成的对象或元组类型。

  1. 通过-号可以将修饰符readonly去掉。

关于-的知识可以查阅官方文档

  1. T[P] extends object ? Mutable<T[P]> : T[P]

通过条件判断,可以对嵌套的对象继续进行处理,直至将T中全部的属性的readonly修饰符去掉。

OmitByType

挑战要求

在线示例

type OmitByType<T, U> = {
  [P in keyof T as T[P] extends U ? never : P]: T[P];
}
  • 关键点就是通过 as 来创建一个新的键类型,由此通过条件判断来排除掉某些键

ObjectEntries

挑战要求

在线示例

type ChangeValue<T> = {
  [P in keyof T]: [P, T[P] extends undefined ? undefined : T[P]]
} 

type ObjectEntries<T> =  ChangeValue<Required<T>>[keyof T];

ObjectEntries最终要返回的类型是一个联合类型,那么针对一个对象,以下操作可行:

type T = {
  a: 1,
  b: 2,
  c: 3
}

// T1 = 'a' | 'b' | 'c'
type T1 = keyof T; 
// T2 = 1 | 2 | 3
type T2 = T[keyof T];

所以,根据上面代码的思路,那么我们只要将类型T的值变为[键, 值]的形式既可,最后通过索引类型就可以返回T中所有值组成的联合类型了。