阅读 84

Typescript 骚操作大全

排除原类型中特定 Key 或者特定 Value

当你要 排除(Omit) 或者 选取(Pick) 某些属性的时候,当然你可以通过 Omit<IOrigin, "key1" | "key2">,但是如果有没有一种方法可以 批量处理 呢,下面就给你演示骚操作

interface IOrigin {   [name: number]: string   name: string   gender: string   age: number   getName: () => string   getGener: () => string   getAge: () => number } /**  * 简单 Omit 排除特定 Key 的属性  * {  *    [name: number]: string;  *    gender: string;  *    age: number;  *    getGener: () => string;  *    getAge: () => number;  * }  */ type OmitSimply = Omit<IOrigin, "name" | "getName"> // 通过 infer 排除特定 Key 的属性 type OmitInferKey<T, R> = {   [K in keyof T as T extends R ? never : K]: T[K] } /**  * 排除 Key 类型为 number 的属性  * {  *    name: string;  *    gender: string;  *    age: number;  *    getName: () => string;  *    getGener: () => string;  *    getAge: () => number;  * }  */ type OmitInferKeyNumber = OmitInferKey<IOrigin, number> /**  * 排除 Key 类型为 `get${string}` 的属性  * {  *    [name: number]: string;  *    name: string;  *    gender: string;  *    age: number;  * }  */ type OmitInferKeyRegExp = OmitInferKey<IOrigin, `get${string}`> // 通过 infer 排除特定 Value 的属性 type OmitInferValue<T, R> = {   [K in keyof T as T[K] extends R ? never : K]: T[K] } /**  * 排除 Value 类型为 Function 的属性  * {  *    [name: number]: string;  *    name: string;  *    gender: string;  *    age: number;  * }  */ type OmitInferKeyFunction = OmitInferValue<IOrigin, Function> 复制代码

这里演示下“排除(Omit)”如何实现,你可以举一反三,实现“选取(Pick)”

类型中某些属性只能“二选一”

当我们不单单要明确定义参数的类型,而且如果参数为 object 的话,还有可能出现 object 里面某两个属性是冲突,只能“二选一”的情况。

interface IMyParams {   a: number;   b: number; } // 如果我们需要将一个参数定义为对象,并且其属性 a 或者 b 必须要传递一个的话 function calc(params: IMyParams): number{   if (params.a) {     console.log(params.a + 1);   } else {     console.log(params.b + 1);   } } 复制代码

下面定义了一个 EitherOr 的类型来处理这种情况:

type FilterOptional<T> = Pick<   T,   Exclude<     {       [K in keyof T]: T extends Record<K, T[K]> ? K : never;     }[keyof T],     undefined   > >; type FilterNotOptional<T> = Pick<   T,   Exclude<     {       [K in keyof T]: T extends Record<K, T[K]> ? never : K;     }[keyof T],     undefined   > >; type PartialEither<T, K extends keyof any> = { [P in Exclude<keyof FilterOptional<T>, K>]-?: T[P] } &   { [P in Exclude<keyof FilterNotOptional<T>, K>]?: T[P] } &   { [P in Extract<keyof T, K>]?: undefined }; type Object = {   [name: string]: any; }; export type EitherOr<O extends Object, L extends string, R extends string> =    (     PartialEither<Pick<O, L | R>, L> |      PartialEither<Pick<O, L | R>, R>   )  & Omit<O, L | R>; 复制代码

使用例子:

// a、b二选一,并且必须传递一个 type RequireOne = EitherOr<   {     a: number;     b: string;   },   'a',   'b' >; // a、b二选一,或者都不传 type RequireOneOrEmpty = EitherOr<   {     a?: number;     b?: string;   },   'a',   'b' >; 复制代码

实际应用:

interface IColumn {   title: string;   dataIndex: string;   render: () => React.ReactNode; } // 熟悉 antd 的同学应该都知道,如果传递了 render 的话,其他 dataIndex 其实就没意义 // 换个角度来说,其实它们两个是“二选一”的属性 interface ITableProps {   columns: Array<     EitherOr<       IColumn,       'dataIndex',       'render'     >   >; } function Table(props: ITableProps){   // TODO }


作者:tellyourmad
链接:https://juejin.cn/post/7025851349103280164


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐