ts 中partial的作用

实现 RequireExactlyOne 工具类型,用于满足以下功能。即只能包含 age 或 gender 属性,不能同时包含这两个属性。具体的使用示例如下所示:

interface Person {
  name: string;
  age?: number;
  gender?: number;
}

// 只能包含Keys中唯一的一个Key
type RequireExactlyOne<T, Keys extends keyof T> = // 你的实现代码

const p1: RequireExactlyOne<Person, 'age' | 'gender'> = {
  name: "lolo",
  age: 7,
};

const p2: RequireExactlyOne<Person, 'age' | 'gender'> = {
  name: "lolo",
  gender: 1
};

// Error
const p3: RequireExactlyOne<Person, 'age' | 'gender'> = {
  name: "lolo",
  age: 7,
  gender: 1
};

答案

type RequireExactlyOne<
  T,
  K extends keyof T,
  Keys extends keyof T = K
> = K extends any
  ? Omit<T, K> & Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, never>>
  : never;

const p1: RequireExactlyOne<Person1, 'age' | 'gender'> = {
  name: 'lolo',
  age: 7,
};

const p2: RequireExactlyOne<Person1, 'age' | 'gender'> = {
  name: 'lolo',
  gender: 1,
};

// Error
const p3: RequireExactlyOne<Person1, 'age' | 'gender'> = {
  name: 'lolo',
  age: 7,
  gender: 1,
};

我有点不理解为什么需要加上image.png
在我的理解中,已经通过extends实现了联合类型的分发机制,那么只需要Omit<T, K> & Required<Pick<T, K>> 就可以实现题目的要求了,Partial<Record<Exclude<Keys, K>, never>>本身是可有可无的,但是去掉这个确实p3不会报错,没有实现题目要求

阅读 4.8k
1 个回答

Partial<Record<Exclude<Keys, K>, never>> 作用是让前面已经 required 的 K 以外的其余 key 变为 never

比如当 K 为 'age' 的时候进来执行这条语句时,前半部分让 'age' 变为 required 了, 后半部分从 Keys('age' | 'gender')中排除了 'age'(即剩下 'gender')后让其对应的值变成了 never

借助 vscode 的错误原因分析其实你就可以知道为啥了(看你的编辑器应该不是 vscode):

image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题