type-challenges:PartialByKeys

52 阅读1分钟

PartialByKeys

问题描述

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

K指定应设置为可选的T的属性集。当没有提供K时,它就和普通的Partial<T>一样使所有属性都是可选的。

例如:

interface User {
  name: string
  age: number
  address: string
}
​
type UserPartialName = PartialByKeys<User, 'name'> // { name?:string; age:number; address:string }
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'interface User {
  name: string
  age: number
  address: string
}
​
interface UserPartialName {
  name?: string
  age: number
  address: string
}
​
interface UserPartialNameAndAge {
  name?: string
  age?: number
  address: string
}
​
type cases = [
  Expect<Equal<PartialByKeys<User, 'name'>, UserPartialName>>,
  Expect<Equal<PartialByKeys<User, 'name' | 'age'>, UserPartialNameAndAge>>,
  Expect<Equal<PartialByKeys<User>, Partial<User>>>,
  // @ts-expect-error
  Expect<Equal<PartialByKeys<User, 'name' | 'unknown'>, UserPartialName>>
]
​
// ============= Your Code Here =============
type Compute<T> = { [K in keyof T]: T[K] }
// 答案1
type PartialByKeys<T extends object, K extends keyof T = keyof T> =  Compute<Omit<T, K> & { [P in K]?: T[P] }>
// 答案2
type PartialByKeys<T, K extends keyof T = keyof T> = Compute<
  { [P in keyof T as P extends K ? never : P]: T[P] } & { [P in K]?: T[P] }
>
​

从原类型中忽略当前的 K值,并且使用联合类型将其变为可选参数,最后在使用类型映射获取所有键值对。

这段代码定义了一个名为PartialByKeys的类型操作符,它接受两个类型参数:T(原始类型)和K(要保留的键的类型)。PartialByKeys的主要目的是从类型T中提取一个新类型,该类型包含K中定义的所有键,以及这些键的默认值。

实现原理:

  1. 使用Compute类型操作符创建一个新类型,该类型包含K中定义的所有键,以及这些键的默认值。
  2. 使用对象展开运算符{ [P in keyof T as P extends K ? never : P]: T[P] }T中提取所有键,但仅当它们是K的一部分时。
  3. 使用对象展开运算符{ [P in K]?: T[P] }K中的每个键添加一个可选属性,以便在需要时提供默认值。