上文中介绍了 对象操作的内置类型的使用,本文介绍几个基于内置类型,扩展的自定义类型,(类型名称自定义的)

将部分属性变为可选属性

实现思路:先将 name 属性挑出来变为可选的 & 除了 name 属性的

// 有时处理类型之后,对象类型结构不明显。只是简单做一个映射,并未其他意义。
type Compute<T extends object> = {
[K in keyof T]: T[K]; // 映射
};
interface Person {
name: string;
age: number;
address: string;
}
// 先将name属性挑出来变为可选的 & 除了name属性的
// Partial<Pick<T, K>> & & Omit<T, K> type PartialPropsOption<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>; type x1 = PartialPropsOption<Person, "name">;
type x2 = Compute<PartialPropsOption<Person, "name">>; // 使用Compute包一层可以看清楚结构,不包也可以

根据值的类型 反选 key

之前的常见做法都是用过 key 值来获取属性,反之,如果根据值的类型 反选 key?

写法一:基础原理写法,使用不同的内置类型,Pick 和 Omit

定义一个接口 Person。通过不同的内置类型,实现挑选 值类型为string的keys过滤 值类型为string的keys

interface Person {
name: string;
age: number;
address: string;
}
// 判断两个类型是否相等
type isEqual<T, U, Success, Fail> = [T] extends [U] ? ([U] extends [T] ? Success : Fail) : Fail; type ExtractKeysByValueType<T, U> = {
[K in keyof T]: isEqual<T[K], U, K, never>;
}[keyof T]; // 找到需要的属性 name | address **注:联合类型中没有never type PickKeysByValue<T, U> = Pick<T, ExtractKeysByValueType<T, U>>;
type PickedKeys = PickKeysByValue<Person, string>; // 挑选 值类型为string的keys 返回 name address type OmitKeysByValue<T, U> = Omit<T, ExtractKeysByValueType<T, U>>;
type OmitedKeys = OmitKeysByValue<Person, string>; // 过滤 值类型为string的keys 返回 age

写法二:基础原理写法,使用 Pick 内置类型 + 传参的方式

interface Person {
name: string;
age: number;
address: string;
}
// 判断两个类型是否相等
type isEqual<T, U, Success, Fail> = [T] extends [U] ? ([U] extends [T] ? Success : Fail) : Fail; type ExtractKeysByValueType<T, U, O = false> = {
[K in keyof T]: isEqual<T[K], U, isEqual<O, true, never, K>, isEqual<O, true, K, never>>;
}[keyof T]; // 找到需要的属性 name | address **注:联合类型中没有never type PickKeysByValue<T, U> = Pick<T, ExtractKeysByValueType<T, U>>;
type PickedKeys = PickKeysByValue<Person, string>; // 挑选 值类型为string的keys 返回 name address type OmitKeysByValue<T, U> = Pick<T, ExtractKeysByValueType<T, U, true>>;
type OmitedKeys = OmitKeysByValue<Person, string>; // 过滤 值类型为string的keys 返回 age

写法三:使用映射条件做双重映射

interface Person {
name: string;
age: number;
address: string;
}
type PickKeysByValue<T extends object, U> = {
// [K in keyof T as `a_${K & string}`]: T[K]; // 使用模板字符串 重命名 // as 语法 映射成一个新的变量
[K in keyof T as T[K] extends U ? K : never]: T[K];
}; type PickKeysByAs = PickKeysByValue<Person, string>; // 挑选 值类型为string的keys 返回 name address

求对象的交集 ObjectInter

交集:指的是类型中的属性属性属性,即存在于 A 中,又存在于 B 中,属性的类型可以不同,取交集后者类型,

type A = {
name: string;
age: number;
address: string;
}; type B = {
name: string;
male: boolean;
address: number;
};
// 返回的是联合类型 name | address
type ObjectInter<T extends object, U extends object> = Pick<U, Extract<keyof T, keyof U>>; type X1 = ObjectInter<A, B>; // 从B中取A,address类型取B中的类型 number

求对象的差集 ObjectDiff

算一下 B - A,使用内置类型组合:Omit + Extract == Pick + Exclude

组合的写法比较多种,只要可以实现就可以,需要注意的是 谁-谁,就是从哪个对象中挑选

type A = {
name: string;
age: number;
address: string;
}; type B = {
name: string;
male: boolean;
address: number;
};
type ObjectDiff<T extends object, U extends object> = Omit<U, Extract<keyof T, keyof U>>;
type X2 = ObjectDiff<A, B>; // B - A = male: boolean; type ObjectDiff2<T extends object, U extends object> = Pick<T, Exclude<keyof T, keyof U>>;
type X3 = ObjectDiff2<A, B>; // A - B = age: number; type OmitDiff<T extends object, U extends Object> = Omit<T, keyof U>;
type X4 = OmitDiff<A, B>; // A - B = age: number;

求对象的并集 ObjectMerge

希望最终得到的结果是 type X7 = { age: number; name: string; address: number; male: boolean;}

实现思路:先找出A - B的差集,再& B

type A = {
name: string;
age: number;
address: string;
}; type B = {
name: string;
address: number;
male: boolean;
};
type Compute<T extends object> = {
[K in keyof T]: T[K]; // 只是做了映射,为了显示类型结果
}; type ObjectMerge<T extends object, U extends object> = Omit<T, keyof U> & U;
type X5 = Compute<ObjectMerge<A, B>>;

求对象的补集 ObjectComp

补集:存在于 A 中,不存在于 B 中,属性相差。互补,注意:双方得存在父子关系,才能互补 也就是 B 是 A 的子类型

type A = {
name: string;
age: number;
address: string;
}; type B = {
name: string;
address: string;
}; // 类型“B” 需要满足约束 “A”。
type ObjectComp<T extends object, U extends T> = Omit<U, Extract<keyof T, keyof U>>;
type X6 = ObjectComp<B, A>; // age: number;

重写对象类型 Overwrite

使用 B 重写 A 中相同的属性,案例中就是 使用 address: string => address: number,其他不变

希望最终得到的结果是 A=> { name: string; age: number; address: number }

实现思路:先找出交集,在找差集,利用上边已经实现的代码

type A = {
name: string;
age: number;
address: string;
}; type B = {
name: string;
address: number;
male: boolean;
};
type Compute<T extends object> = {
[K in keyof T]: T[K]; // 只是做了映射,为了显示类型结果
}; type Overwrite<T extends object, U extends object> = ObjectInter<A, B> & ObjectDiff2<A, B>;
type X7 = Compute<Overwrite<A, B>>;

TypeScript 学习笔记 — 自定义类型:部分属性可选,反选 key,求对象交差并补集等(十三)的更多相关文章

  1. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  2. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  3. Typescript 学习笔记三:函数

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  4. SQL反模式学习笔记6 支持可变属性【实体-属性-值】

    目标:支持可变属性 反模式:使用泛型属性表.这种设计成为实体-属性-值(EAV),也可叫做开放架构.名-值对. 优点:通过增加一张额外的表,可以有以下好处 (1)表中的列很少: (2)新增属性时,不需 ...

  5. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. Typescript 学习笔记二:数据类型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  8. Typescript 学习笔记一:介绍、安装、编译

    前言 整理了一下 Typescript 的学习笔记,方便后期遗忘某个知识点的时候,快速回忆. 为了避免凌乱,用 gitbook 结合 marketdown 整理的. github地址是:ts-gitb ...

  9. TypeScript学习笔记(八):1.5版本之后的模块和命名空间

    我之前有写过TS1.5版本之前的“模块”的笔记:TypeScript学习笔记(七):模块 但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以 ...

  10. iOS学习笔记-自定义过渡动画

    代码地址如下:http://www.demodashi.com/demo/11678.html 这篇笔记翻译自raywenderlick网站的过渡动画的一篇文章,原文用的swift,由于考虑到swif ...

随机推荐

  1. 【Delphi7官方镜像版】delphi_7_ent_en官方镜像 阿里云盘

    [Delphi7官方镜像版]「delphi_7_ent_en官方镜像.iso.exe」https://www.aliyundrive.com/s/Du9C4XfZfwG 点击链接保存,或者复制本段内容 ...

  2. 20200921--同行列对角线的格(奥赛一本通P89 2 二维数组)

    输入三个自然数n,i,j(1<=i<=n,1<=j<=n),输出在一个n*n格的棋盘中(行列均从1开始编号),与格子(i,j)同行,同列,同一对角线的所有格子的位置. 如:n= ...

  3. MYSQL面试题大汇总

    1.数据库的三大范式是什么 1)列不可再分 2)行可以唯一区分 3)表的非主属性不可以依赖与其他表的非主属性,外键约束 2.数据库中的事务 1)什么是事务:多条sql语句,要么都成功,要么都失败 2) ...

  4. vue项目中 vscode 保存时自动格式化设置,保持单引号和去除多余分号、逗号

    1.settings.json中添加: "prettier.semi": false, // 取消自动加分号 "prettier.singleQuote": t ...

  5. 什么是Vuex

    Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享. 优点: 能够在Vuex中集中管理共享的数居,易于开发和后期维护 能够高效地实现组件之间的数据共享,提高开发效率 存 ...

  6. LocalDateTime接收前端String格式

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; 实体类属性添加注解,前 ...

  7. 如何修改被编译后DLL文件 (转发)

    我们平时在工作中经常会遇到一些已经被编译后的DLL,而且更加麻烦是没有源代码可以进行修改,只能针对这个DLL的文件进行修改才能得到我们想要的结果:本文将通过一个实例来演示如果完成一个简单的修改;我们将 ...

  8. Okhttp请求

    theme: juejin highlight: a11y-dark 同步请求 OkHttpClient httpClient = new OkHttpClient(); String url = & ...

  9. connect及bind、listen、accept背后的三次握手

    如图所示打上断点,分别找出connect() bind() listen() accpet()对应的函数 源码在上一次作业中已经分析过了 https://www.cnblogs.com/qwertyu ...

  10. VBA类模块完全教程(www.accessoft.com软件网)

    这份礼物送给现在想学习类知识或曾经学过但因为各种原因没有"修成正果"的朋友,我期望的结果是这篇文章后,您可以在类模块中像在标准模块中写代码一样熟练,我也期望不至于太乏味而使您没有耐 ...