RequiredByKeys
问题描述
实现一个通用的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>>
]
type Compute<T extends object> = { [K in keyof T]: T[K] }
// ============= Your Code Here =============
// 答案1
type RequiredByKeys<T extends object, K extends keyof T = keyof T> = Compute<Omit<T, K> & Required<Pick<T, K>>>
// 答案2
type RequiredByKeys<T, K extends keyof T = keyof T> = Omit<T & Required<Pick<T, K & keyof T>>, never>;
思路其实很简单,和上一题刚好相反,只需要将第二个泛型参数从类型中剔除出来并将其变成必选属性,使用联合类型传入 Compute 类型中映射为一个新的类型即可。
答案1
这段代码定义了一个名为RequiredByKeys的类型操作符,它接受两个类型参数T和K。T表示对象类型,K表示键类型。RequiredByKeys的实现原理是使用Compute类型操作符和Omit和Pick两个类型操作符。
Compute<Omit<T, K> & Required<Pick<T, K>>>:这是RequiredByKeys的实现。Omit<T, K>表示从类型T中移除键K,Required<Pick<T, K>>表示从类型T中选择键K,但确保它们在对象中存在。T extends object:表示T必须是一个对象类型。K extends keyof T = keyof T:表示K必须是一个键类型,并且默认情况下等于T的键类型。
答案2
这段代码定义了一个名为RequiredByKeys的类型操作符,它接受两个类型参数T和K。T是原始对象类型,K是键的类型,默认为keyof T。
实现原理:
- 使用
Required<Pick<T, K & keyof T>>创建一个新对象,其中K & keyof T是对象的键,Pick<T, K & keyof T>是从原始对象中选择这些键的子集。Required<T>会确保对象中的所有属性都是必需的(即不会为undefined或null)。 - 使用
Omit<T & Required<Pick<T, K & keyof T>>, never>创建一个新对象,其中T & Required<Pick<T, K & keyof T>>是必需的原始对象,Omit<T & Required<Pick<T, K & keyof T>>, never>会从必需的原始对象中移除所有键为never的属性。