题目描述
实现一个通用的RequiredByKeys<T, K>,它接收两个类型参数T和K。
K指定应设为必选的T的属性集。当没有提供K时,它就和普通的Required<T>一样使所有的属性成为必选的。
例如:
interface User {
name?: string
age?: number
address?: string
}
type UserRequiredName = RequiredByKeys<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 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' | 'age'>, UserRequiredNameAndAge>>,
Expect<Equal<RequiredByKeys<User>, Required<User>>>,
// @ts-expect-error
Expect<Equal<RequiredByKeys<User, 'name' | 'unknown'>, UserRequiredName>>,
]
// ============= Your Code Here =============
type MergeIntersection<T> = {
[P in keyof T]: T[P]
}
type RequiredByKeys<
T,
K extends keyof T = keyof T
> = MergeIntersection<
& T
& Required<
Pick<T, K>
>
>
类型操作
-
MergeIntersection<T>:-
这个类型的作用是将一个交叉类型中的所有属性合并成一个单一的类型
-
{ [P in keyof T]: T[P] }:遍历T的所有键,将每个键的值类型提取出来,形成一个新的类型
-
-
RequiredByKeys<T, K>:-
K extends keyof T = keyof T:K是一个联合类型,表示要使哪些属性变为必选。如果没有提供K,则默认为keyof T,即所有属性都变为必选 -
Pick<T, K>:从T中选择K指定的属性 -
Required<Pick<T, K>>:将Pick<T, K>的结果中的所有属性变为必选 -
T & Required<Pick<T, K>>:将原始类型T和变为必选的属性合并 -
MergeIntersection<...>:将合并后的交叉类型中的所有属性合并成一个单一的类型
-