# 57-获取必填属性
# 题目描述
实现高级 util 类型GetRequired<T>
,该类型保留所有必填字段
例如
type I = GetRequired<{ foo: number; bar?: string }>; // expected to be { foo: number }
# 分析
可选属性的特点是,给最终的类型中增加一个 undefined,那么其实遍历一遍属性,看看属性值中是否有 undefined,就可以看出哪些属性需要过滤了。
但是要注意,原本属性值就是 undefined 的情况,也就是 bar?: undefined
和 bar: 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];
};
# 知识点
- 可选属性对
T[P]
的影响: 增加 undefined 属性 e?: undefined
去除可选修饰符后,返回 never