# 57-获取必填属性

# 题目描述

实现高级 util 类型GetRequired<T>,该类型保留所有必填字段

例如

type I = GetRequired<{ foo: number; bar?: string }>; // expected to be { foo: number }

# 分析

可选属性的特点是,给最终的类型中增加一个 undefined,那么其实遍历一遍属性,看看属性值中是否有 undefined,就可以看出哪些属性需要过滤了。

但是要注意,原本属性值就是 undefined 的情况,也就是 bar?: undefinedbar: undefined,对于这种情况,上述方法无法检测到。

那么换一种思路,生成一个去除了可选修饰符的新类型,遍历属性,判断当前类型的属性值和新类型的属性值是否相等,就可以解决问题。

type Case1 = {
  a?: 1;
  d: undefined;
  e?: undefined;
};

/*
    a: 1;
    d: undefined;
    e: never;
*/
type RequiredCase1 = Required<Case1>;

对于普通属性来讲,Required 后的属性值去除了 undefiend,对于 d: undefined,Required 后的属性值还是 undefined,而 e?: undefined 之后是 never(可以理解为 -? 的作用,就是把属性值中的 undefined 去除,在 e 这个场景,就是 Exlucde<'undefined', 'undefined'> 自然是 never 了),根据这个特点,通过比较 T[P]Required<T>[P] 就可以筛选出来目标属性

# 题解

type GetRequired<T> = {
  [P in keyof T as T[P] extends Required<T>[P] ? P : never]: T[P];
};

# 知识点

  1. 可选属性对 T[P] 的影响: 增加 undefined 属性
  2. e?: undefined 去除可选修饰符后,返回 never
Last Updated: 2023/5/16 06:00:28