PartialByKeys
问题描述
实现一个通用的PartialByKeys<T, K>,它接收两个类型参数T和K。
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中定义的所有键,以及这些键的默认值。
实现原理:
- 使用
Compute类型操作符创建一个新类型,该类型包含K中定义的所有键,以及这些键的默认值。 - 使用对象展开运算符
{ [P in keyof T as P extends K ? never : P]: T[P] }从T中提取所有键,但仅当它们是K的一部分时。 - 使用对象展开运算符
{ [P in K]?: T[P] }为K中的每个键添加一个可选属性,以便在需要时提供默认值。