Typescript - - 高级用法

news/2024/11/28 16:03:40/

Typescript - - 高级用法

extends

extends 关键字在TS中的两种用法,即接口继承和条件判断。

接口继承

 interface T1 {name: string}interface T2 {sex: number}// 多重继承,逗号隔开interface T3 extends T1,T2 {age: number}// 合法const t3: T3 = {name: 'xiaoming',sex: 1,age: 18}

T1和T2两个接口,分别定义了name属性和sex属性,T3则使用extends使用多重继承的方式,继承了T1和T2,同时定义了自己的属性age,此时T3除了自己的属性外,还同时拥有了来自T1和T2的属性。

条件判断

  // 示例1interface Animal {eat(): void}interface Dog extends Animal {bite(): void}// A的类型为stringtype A = Dog extends Animal ? string : numberconst a: A = 'this is string'

Extends 用来条件判断的语法和 JS 的三元表达是很相似,如果问号前面的判断为真,则将第一个类型 string 赋值给 A,否则将第二个类型 number 赋值给 A。

extends判断条件真假的逻辑是什么?
如果 extends 前面的类型能够赋值给 extends 后面的类型,那么表达式判断为真,否则为假

泛型使用

TypeScript: Documentation - Conditional Types

  type A1 = 'x' extends 'x' ? string : number; // stringtype A2 = 'x' | 'y' extends 'x' ? string : number; // numbertype P<T> = T extends 'x' ? string : number;type A3 = P<'x' | 'y'> // string | number

!!!注意!!! :
When conditional types act on a generic type, they become *distributive* when given a union type
对于使用extends关键字的条件类型(即上面的三元表达式类型),如果extends前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用分配律计算最终的结果。分配律是指,将联合类型的联合项拆成单项,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。 所以上面的 A3 是 string | number
满足两个要点即可适用分配律:第一,参数是泛型类型,第二,代入参数的是联合类型
特别要注意的就是 never

  // never是所有类型的子类型type A1 = never extends 'x' ? string : number; // stringtype P<T> = T extends 'x' ? string : number;type A2 = P<never> // never
/* 
A2 和 A1 的结果竟然不一样,看起来 never 并不是一个联合类型,所以直接代入条件类型的定义即可,获取的结果应该和A1一直才对啊?
实际上,这里还是条件分配类型在起作用。never 被认为是空的联合类型,也就是说,没有联合项的联合类型,所以还是满足上面的分配律,然而因为没有联合项可以分配,所以 P<T> 的表达式其实根本就没有执行,所以 A2 的定义也就类似于永远没有返回的函数一样,是never类型的。
*/

防止类型分配

type P<T> = [T] extends ['x'] ? string : number;
type A1 = P<'x' | 'y'> // number
type A2 = P<never> // string
// 在条件判断类型的定义中,将泛型参数使用[]括起来,即可阻断条件判断类型的分配,此时,传入参数T的类型将被当做一个整体,不再分配。

keyof

keyofObject.keys 略有相似,只不过 keyof 取interface 的键。

interface Point {x: number;y: number;
}
// 相当于:
// type keys = "x" | "y"
type keys = keyof Point;

实现一个函数,这个函数获取到一个对象的 value,参数是这个对象和 key

const object = {a: 1,b: 'zhangsan'
}
// 这样实现的弊端,1、 key 没有限定,我可以取 a、b 之外的了,2、返回的值没有限定,直接用 any 了
function get(obj: object, key: string): any {return obj[key]
}// 改造
function get<T extends object, U extends keyof T>(obj: T, key: U): T[U] {return obj[key]
}
interface Person {name: string;age: number;location: string;
}type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[];  // number | "length" | "push" | "concat" | ...
type K3 = keyof { [x: string]: Person };  // string | number.  这个的解释可以参考下面的链接

TypeScript: Documentation - TypeScript 2.9

Partial & Required & Pick

Typescript 已实现的,可以通过下面的去类比学习便于理解

type Partial<T> = {[P in keyof T]?: T[P];
};type Required<T> = {[P in keyof T]-?: T[P];
};type Pick<T, K extends keyof T> = {[P in K]: T[P];
};interface User {id: number;age: number;name: string;
};// 相当于: type PartialUser = { id?: number; age?: number; name?: string; }
type PartialUser = Partial<User>// 相当于: type PickUser = { id: number; age: number; }
type PickUser = Pick<User, 'id' | 'age'>

never & Exclude & Extract & Omit

type Exclude<T, U> = T extends U ? never : T;// 相当于: type A = 'a'
type A = Exclude<'x' | 'a', 'x'>
type A = Exclude<'x' | 'a', 'x' | 'y' | 'z'>// 与 Exclude 实现刚好相反,Exclude 取差集,而 Extract 取交集
type Extract<T, U> = T extends U ? T : never;// 相当于: type A = 'x'
type A = Exclude<'x' | 'a', 'x'>type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
/* Omit 讲解
1、 keyof T 获取 T 的 key
2、 Exclude<keyof T, K> , K 就是我们要忽略的键,Exclude 找到 两个的差集
3、 Pick<T, 差集> 获取到的就是我们忽略了 K 后面留下来的
*/interface User {id: number;age: number;name: string;
};// 相当于: type PickUser = { age: number; name: string; }
type OmitUser = Omit<User, "id">

typeof

typeof 代表取某个值的 type

const a: number = 3
// 相当于: const b: number = 4
const b: typeof a = 4

http://www.ppmy.cn/news/3387.html

相关文章

[附源码]Node.js计算机毕业设计服装销售商城系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

Mapbox 与 Babylon.js 可视化 glsl 特效篇(三十九)

我决定不从Babylonjs 基础来讲了 直接整合mapbox与babylonjs可视化来讲 我整合一个类库 后续不断更新中 npm i haibalai/mapbox-babylonjs 初始化mapbox-babylonjs 类库&#xff0c; map 是mapbox.gl 的map 对象 import { BabylonMapManager } from “haibalai/mapbox-baby…

如何管理客商主数据,附要点和QA

客商主数据&#xff08;客户、供应商、既是客户也是供应商&#xff09;是企业最常用的主数据类型之一。要实现上下游的打通&#xff0c;方便企业内部相关业务的运转以及信息流通&#xff0c;做好客商主数据的管理至关重要。 什么是客商主数据 客商主数据是一类复杂的主数据&a…

图书商城小程序开发,实现图书便捷式选购

1995年联合国教文组织将4月23日规定为世界读书日&#xff0c;由此可见对全世界人民来说读书都是一件很重要的事。并且据调查数据显示&#xff0c;去年我国成年国民图书阅读量达到了59.7%&#xff0c;同比增长了0.2个百分点&#xff1b;人均纸质图书阅读量为4.76&#xff0c;较上…

深蓝学院-多传感器融合定位课程-第7章-基于滤波的融合方法I

专栏文章: 深蓝学院-多传感器融合定位课程-第1章-概述_goldqiu的博客-CSDN博客 深蓝学院-多传感器融合定位课程-第2章-3D激光里程计I_goldqiu的博客-CSDN博客 深蓝学院-多传感器融合定位课程-第3章-3D激光里程计II_goldqiu的博客-CSDN博客 深蓝学院-多传感器融合定位课程-第…

未能加载文件或程序集XXX.dll,程序启动失败的解决方案

之前在VS2019上下载一个项目&#xff0c;运行后就报错&#xff0c;弹出 出错&#xff1a;未能加载文件或程序集XXX.dll 我们选中该dll&#xff0c;右键&#xff0c;属性&#xff0c;发现 该dll被锁定 点击“解决锁定”即可解决。 为了一劳永逸解决此问题&#xff0c;后到微软…

老油条用什么工具写文档?

写代码&#xff0c;哪个程序员都不害怕。 写文档&#xff0c;哪个程序员都害怕&#xff01; 为什么&#xff1f; 还不是因为 API 工具不好使&#xff0c;不便捷&#xff0c;同步麻烦&#xff0c;测试看不懂…… 最近调研了身边一些开发团队&#xff0c;发现他们列举的工具中…

Word处理控件Aspose.Words功能演示:在 Java 中将 Word DOCX 转换为 Markdown

如今&#xff0c;Markdown ( MD ) 格式被广泛用于编写在线文章、博客和文档。但是&#xff0c;在大型文档的情况下&#xff0c;它的语法变得难以记忆和书写。为方便起见&#xff0c;您可以在 MS Word 中编写内容&#xff0c;然后将DOCX文件转换为 Markdown。为了以编程方式执行…