ts类型挑战【二十三】

210 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

题目四十:requiredbykeys

// template.ts
type RequiredByKeys<T, K> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'

interface User {
  name?: string
  age?: number
  address?: string
}

interface UserRequiredName {
  name: string
  age?: number
  address?: string
}

interface UserRequiredNameAndAge {
  name: string
  age: number
  address?: string
}

type cases = [
  Expect<Equal<RequiredByKeys<User, 'name'>, UserRequiredName>>,
  Expect<Equal<RequiredByKeys<User, 'name' | 'unknown'>, UserRequiredName>>,
  Expect<Equal<RequiredByKeys<User, 'name' | 'age'>, UserRequiredNameAndAge>>,
  Expect<Equal<RequiredByKeys<User>, Required<User>>>,
]

实现一个通用的 RequiredByKeys<T,K>,它接受两种类型的参数 TK

K指定应设置为必需的T属性集。当没有提供 K 时,它应该使所有所需的属性都像正常的 required<T> 一样。

测试用例

User 中有三项,都是可选属性

  • RequiredByKeys<User, 'name'>

Userkeyname 的项改为必填的

  • RequiredByKeys<User, 'name' | 'unknown'>

unknown 会被忽略

  • RequiredByKeys<User, 'name' | 'age'>

如果传入的是联合属性,则将联合属性中的每一项都改为必填

  • RequiredByKeys<User>

如果没传第二个参数,则和 Required 方法效果一致

required

我们先来看一下 TS 内置的 required 方法

type Required<T> = {
    [P in keyof T]-?: T[P];
};

作用:将全部项都外给必填(去掉可选 ?

代码实现

  • 原代码
type RequiredByKeys<T, K> = any
  • K 的默认值是 T 的全部 key
type RequiredByKeys<T, K = keyof T> = any
  • 拿出 TkeyK 的内容
type RequiredByKeys<T, K = keyof T> = Pick<T, K & keyof T>
  • 将其转换为必填的
type RequiredByKeys<T, K = keyof T> = Required<Pick<T, K & keyof T>>
  • 与剩余的 T 中的内容合并
type RequiredByKeys<T, K = keyof T> = Required<Pick<T, K & keyof T>>
	& Omit<T, K & keyof T>
  • 因为使用了合并,所以需要在复制一下
type Copy<T> = {
  [P in keyof T]: T[P]
}
type RequiredByKeys<T, K = keyof T> = Copy<
  Required<Pick<T, K & keyof T>> 
  & Omit<T, K & keyof T>
>

题目四十一:mutable

// template.ts
type Mutable<T> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'

interface Todo1 {
  title: string
  description: string
  completed: boolean
  meta: {
    author: string
  }
}

type cases = [
  Expect<Equal<Mutable<Readonly<Todo1>>, Todo1>>,
]

实现通用的Mutable<T>,它使T中的所有属性都是可变的(而不是只读的)。

代码实现

  • 原代码
type Mutable<T> = any
  • 遍历对象
type Mutable<T> = {
  [P in keyof T]: T[P]
}
  • 在遍历过程中,祛除 readonly 修饰符
type Mutable<T> = {
  - readonly [P in keyof T]: T[P]
}