TS属性排除必填项/非必填项

505 阅读1分钟

1. 先定义一个Person类型

interface PersonProps {
	name: string;
	age?: number;
	email?: string;
}

2. 写一个排除必填项的类型

type PartialPropsOnly<T> = {
	// 如果 T 是 Record<K, T[K]> 的超集,则是必填项,为never,在新的TS类型中就去掉了这个选项
	[K in keyof T as T extends Record<K, T[K]> ? never : K]: T[K];
};
type PartialProps = PartialPropsOnly<PersonProps>;
// 结果可以看出,PartialProps 是OK的
// { age?: number; email?: string; }

3. 尝试增加第二个参数,true/false

type FilterPropsIsRequired<T, S extends boolean> = {
  [K in keyof T as T extends Record<K, T[K]>
   ? S extends true
   ? K
   : never
   : S extends true
   ? never
   : K]: T[K];
};

4. 将FilterPropsIsRequired再次整合

type FilterPartial<T> = FilterPropsIsRequired<T, false>;
type FilterRequired<T> = FilterPropsIsRequired<T, true>;

type RequiredProps = FilterPartial<PersonProps>;
// { name: string; }
type PartialProps = FilterRequired<PersonProps>;
// { age?: number; email?: string; }

至此,我们就完成了在TS属性排除必填项/非必填项的功能。