TypeScript学习笔记之二(高级类型)
文章目录
- 一、TypeScript高级类型
- 1.1 class类
- 1.2 class继承
- 1.3 class类成员可见性
- 1.4 readonly
- 1.5 类型兼容性
- 1.5.1 对象之间的类型兼容性
- 1.5.2 接口之间类型兼容性
- 1.5.3 函数之间类型兼容性
- 1.6 交叉类型
- 1.7 交叉类型(&)和继承(extends)的对比
- 二、泛型
- 2.1 泛型约束--指定更具体的类型
- 2.2 泛型约束--extends添加约束
- 2.3 多个泛型变量
- 2.4 泛型接口
- 2.5 泛型类
- 2.6 泛型工具类Parital\<Type\>
- 2.7 泛型工具类Readonly\<Type>
- 2.8 泛型工具类Pick\<Type, Keys>
- 2.9 泛型工具类Record\<Keys, Type>
- 三、索引签名类型
- 四、映射类型
一、TypeScript高级类型
1.1 class类
TypeScrtip全面支持ES2015中引入的class关键字,并为其添加了类型注解和其他语句
class基本使用
TS中的class,不仅提供了class的语法功能,也作为一种类型存在
class Person {}
const p:Person = new Person()
实例属性初始化
class Person {name: string = "kangyun";gender = "男";
}
const p: Person = new Person();
构造函数
构造函数:为class类的实例属性初始化值的
构造函数不需要返回值
class Person {name: string;gender: string;constructor(name: string, gender: string) {this.name = name;this.gender = gender;}
}
const p: Person = new Person('张三', '男');
</script>
类的实例方法
class Person {name: string;gender: string;constructor(name: string, gender: string) {this.name = name;this.gender = gender;}// 方法的类型注解(参数和返回值)与函数用法相同sayHello(name: string): void {console.log(`hello,${name}`);}
}
const p: Person = new Person("张三", "男");
p.sayHello("李四");
1.2 class继承
类继承的两种方式:
- extends(继承父类)
- implements(实现接口)
JS中只有extends,而implements是TS提供的
class Animail {move() {console.log("Moving!");}
}class Dog extends Animail {bark() {console.log("汪汪......");}
}
// 子类Dog继承父类Animal,则Dog的实例对象dog就同时具有了父类
// Animal和子类Dog的所有属性和方法
const dog: Dog = new Dog();
dog.move();
dog.bark();
interface Singable {name: string;sing: () => void;
}
// Person类实现接口Singable就必须提供Singble接口中指定的方法和属性
class Person implements Singable {name = "张三";sing() {console.log("开始黄牛叫了......");}
}
1.3 class类成员可见性
可见性修饰符包括:
- public 公有的
- proected 受保护的
- private 私有的
public表示公共、公有的,公有成员可以被任何地方访问
public: 是默认可见性,所以可以直接少略
class Animal{public move(){console.log('moving!')}
}
protected: 表示受保护的,仅对其所在类和子类中(非实例对象)可见
在子类的方法内部可以通过this来访问父类中受保护的成员,但是对实例不可见
class Animal {protected move() {console.log("moving");}
}
class Dog extends Animal {bark() {console.log("汪汪......");this.move();}
}
const dog = new Dog();
dog.bark();
private: 表示私有的,只在当前类中可见,对实例对象以及子类也是不可见的
class Animal {private move() {console.log("moving");}walk(){this.move()}
}
1.4 readonly
readonly表示只读,用来防止在构造函数之外对属性进行赋值
class Animal {readonly age: number;constructor(age: number) {this.age = age;}
}
- readonly只能修饰属性不能修饰方法
- 接口或者{}表示的对象类型,也可以使用readonly修饰
1.5 类型兼容性
两种类型系统
- Structural Type System(结构化类型系统)
- Nominal Type System(标明类型系统)
TS采用的是结构化类型系统,类型检查关注的是值所具有的形状
在结构类型系统中如果两个对象具有相同的形状态,则认为它们属性同一类型
class Point01{x: number, y: number}
class Point02{x: number, y: number}
const p:Poing01 = new Point02()
因为TS是结构化类型系统,只检查Point01和Point02的结构是否相同(相同,都具有x和y两个属性,属性类型也相同)
但是如果在标明类型系统(如c#和java中)它们是不同的类,类型无法兼容。
1.5.1 对象之间的类型兼容性
对于对象类型来说,y的成员至少与x相同,则x兼容y(成员多的可以赋值给少的)
class Point {x: number; y: number}
class Point3D {x: number; y:number: z:number}
const p:Point = new Point3D()
1.5.2 接口之间类型兼容性
接口之间的兼容性类似于class,并且class和interface之间也可以兼容
interface Point {x:number; y:number}
interface Point2D {x:number; y:number}
let p1: Point
let p2: Point2D = p1
interface Point3D {x:number; y:number; z:number}
let p3:Point3D
p2 = p3
1.5.3 函数之间类型兼容性
函数之间兼容性比较复杂,需要考虑参数个数、参数类型、返回值类型
参数个数,参数多的兼容参数少的(或者说参数少的可以赋值给多的)
type F1 = (a:number)=>void
type F2 = (a:number, b:number) => void
let f1: F1
let f2: F2 = F1
- 参数少的可以赋值给参数多的,所以f1可以赋值给f2
- 数组forEach方法的第一个参数是回调函数,该示例中类型为(value: string, index: number, array: string[])=>void
- 在JS中省略用不到的函数参数实际是很常见的,这样的使用方式,促成了TS中函数类型之间的兼容性
- 并且因为回调函数是有类型的,所以TS会自动推导出参数item、index、array的类型
***参数类型,***相同位置的参数类型要相同
type F1 = (a:number) => string
type F2 = (a:number) => string
let f1: F1
let f2: F2 = F1
函数类型F2兼容函数类型F1,因为F1和F2的第一个参数类型相同。
interface P2D {x:number; y:number}
interface P3D {x:number; y:number; z:number}
type F2 = (p:P2D)=>void
type F3 = (p:P3D)=>void
left f2: F2
let f3: F3 = f2
技巧:将对象拆开,把每个属性看做一个一个的参数,则参数少的f2可以赋值给参数多的f3。
返回值类型,只关注返回值类型本身即可
type F5 = () => string
type F6 = () => string
let f5: F5
let f6: F6 = f5
type F7 = () => {name: string}
type F8 = () => {name: string, age: number}
let f7: F7
let f8: F8
// 返回的是对象,对象多的可以赋值给少的
f7 = f8
1.6 交叉类型
交叉类型(&):类似于接口继承,用于组合多个类型为一个类型(常用于对象类型)
interface Person {name: string}
interface Contact {phone: string}
type PersonDetail = Person & Contact
let obj: PersonDetail = {name: 'Bill',phone: '15220......'
}
使用交叉类型后,新的类型PersonDetail就同时具备了Person和Contact的所有属性类型,这和继承很相似。
1.7 交叉类型(&)和继承(extends)的对比
相同点:都可实现对象类型的组合
不同点:两种方式实现类型组合时,对于同名属性之间,处理类型冲突的方式不同。
interface A {fn:(value: number) => string
}
interface B extends A {fn: (value: string) => string
}
上示代码接口继承会报错(类型不兼容)
interface A{fn:(value: number) => string
}
interface B{fn:(value: string) => string
)
type C = A & B
C的结果会是: fn:(value: number|string) => string
二、泛型
泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而实现复用,常用于函数、接口、class中。
泛型是用来实现可复用组件功能的主要工具之一。
创建泛型函数
function id<Type>(value: Type):Type { return value}
PS:
在函数名称后面添加<>尖括号,尖括号中添加类型变量,如此处Type,类型变量Type,是一种特殊类型的变量,它处理类型而不是值。该类型变量相当于一个类型容器,能够捕获用户提供的类型(具体是什么类型由用户调用该函数时指定)。因为Type是类型,因此可以将其作为函数参数和返回值的类型,类型变量Type,可以是任意合法的变量名称。
调用泛型函数
const num = id<number>(10)
const str = id<string>('hello')
PS:
当传入类型number后,这个类型就能会被函数声明时指定的类型变量Type捕获到。这样,通过泛型就做到了让id函数与多种不同的类型一起工作,实现了复用的同时保证了类型安全。
简化调用泛型函数
function id<Type>(value: Type):Type { return value}
let num01 = id<number>(10)
let num02 = id(10) //简化
简化由TS类型参数推断,当编译器无法推断类型或者推断的类型不准确时,就需要显式地传入类型参数。
2.1 泛型约束–指定更具体的类型
***泛型约束:***默认情况下,泛型函数的类型变量Type可以代表多个类型,这导致无法访问任何属性。
如:id(‘a’)调用函数时获取参数的长度
function id<Type>(value: Type): Type{console.log(value.length)return value
}
PS:
Type可以代表任意类型,无法保证一定存在length属性,如number就没有length,此时就需要为泛型添加约束来收缩类型。
指定更具体的类型
function id<Type>(value: Type[]): Type[]{console.log(value.length)return value
}
将类型Type修改为Type[](Type类型的数组),因为只要是数组就一定存在Length。
2.2 泛型约束–extends添加约束
添加约束
interface ILength{ length: number }
function id<Type extends ILength>(value: Type): Type{console.log(value.length)return value
}
PS:
通过extends关键字使用该接口,为泛型(类型变量)添加约束,该约束表示:传入的类型必须具有length属性
2.3 多个泛型变量
泛型的类型变量可以有多个,并且类型变量之间还可以约束。
// Key extends keyof Type
// Key的值必须是Type类的key
function getProp<Type, Key extends keyof Type>(obj: Type, key: Key){reutnr obj[key]
}
let person = {name: 'kk', age: 18 }
getProp(person, 'name')
keyof关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型
2.4 泛型接口
泛型接口:接口也可以配合泛型来使用,以增加其灵活性,增强复用性
interface IdFunc<Type>{id: (value: Type) => Typeids: () => Type[]
}
let obj:IdFunc<number>{id(value){return value},ids(){ return [1, 2, 3] }
JS中的数组在TS中就是一个泛型接口
const strs = ['a', 'b', 'c']
2.5 泛型类
class GenericNumber<NumberType>{defaultValue: NumberTypeadd: (x: NumberType, y: NumberType) => NumberType
}
PS:
类似于泛型接口,在class名称后添加<类型变量>这个类就成了泛型类,add方法采用的是箭头函数形式书写方式。
const myNum = new GenericNumber<number>()
myNum.defaultValue = 10
2.6 泛型工具类Parital<Type>
泛型工具类Parital<Type>用来构造(创建)一个类型,将Type的所有属性设置为可选。
interface Props {id: number,children: number[]
}
type ParitalProps = Parital<Props>
PS:构造出来的新类型ParitalProps结构和Props相同,但所有属性都变为可选的。
2.7 泛型工具类Readonly<Type>
泛型工具类Readonly<Type>用来构造一个类型,将Type的所有属性都设置为readonly(只读)
interface Props{id: stringchildren: number[]
}
type ReadonlyProps = Readonly<Props>
解释:构造出来的新类型ReadonlyProps结构和Props相同,但所有属性都变为只读
let props: ReadonlyProps = {id: '1', children: [] }
props.id = '2' //error
重新给id属性赋值,会报错,因为它是只读属性。
2.8 泛型工具类Pick<Type, Keys>
泛型工具类Pick<Type, Keys>从Type中选择一组属性来构造新类型
interface Props{id: stringtitle: stringchildren: number
}
type PickProps = Pick<Props, 'id'|'title'>
Pick工具类型有两个类型变量:
- 表示选择谁的属性
- 表示要选择哪几个属性
构造出来的PickProps只有id和title两个属性类型。
2.9 泛型工具类Record<Keys, Type>
泛型工具类Record<Keys, Type>构造一个对象类型,属性键为Keys,属性类型为Type
type RecordObje = Record<'a'|'b'|'c', string[]>
let obj: RecordObje = {a: ['a'],b: ['2'],c: ['aaa]
}
PS:
Record工具类型有两个类型变量
1、表示对象有哪些属性
2、表示对象属性的类型
三、索引签名类型
绝大多数情况下,我们都可以在使用对象前就确定对象的结构,并为对象添加准确的类型。
当无法确定对象中有哪些属性(或者说对象中可以出现任意多个属性)此时就用到索引签名类型了。
interface AnyObject{[key: string]: number
}
let obj: AnyObject = {a: 1, b: 2,
}
PS:
使用[key: string]来约束该接口中允许出现的属性名称。表示只要是string类型的属性名称,都要以出现在对象中。
key只是一个占位符,可以换成任意合法的变量名称。
四、映射类型
映射类型:基于旧类型创建新类型(对象类型)
type PropKeys = 'x' | 'y' | 'z'
type Type1 = { x:number; y: number; z: number }
上例有太多重复的代码
type PropKeys = 'x' | 'y' | 'z'
type Type2 = { [Key in PropKeys]: number}
映射类型是基于索引签名类型的,所以该语法类似于索引签名类型
映射类型只能在类型别名中使用,不能在接口中使用
映射类型keyof
映射类型除了根据联合类型创建新类型外,还可以根据对象类型来创建
type Props = {a: number; b: string; c: boolean}
type Type = { [key in keyof Props]: number }
PS:
先执行keyof Props获取到对象类型Props中所有键的联合类型即’a’|‘b’|‘c’
然后key in …就表示key可以是Props中所有的键名称中的任意一个
像泛型工具类型Parital<Type>这些都是基于映射类型实现的
type Parital<T> = {[P in keyof T]?: T[P]
}
T[p]在TS中叫做查询(访问)类型
用来查询属性的类型
type Props = {a: number; b: string; c: boolean}
type TypeA = Props['a'] // type TypeA = number
注意:[]中的属性必须存在于被查询类型中,否则就会报错。
索引查询类型的其他使用方式:同时查询多个索引的类型
type Props = {a: number; b: string; c: boolean}
type TypeA = Props['a'|'b']
使用字符串字面量的联合类型,获取属性a和b对应的类型结果为string|number
type TypeA = Props[keyof Props]
使用keyof操作符获取Props中所有键对应的类型,结果为number|string|boolean
相关文章:

TypeScript学习笔记之二(高级类型)
文章目录一、TypeScript高级类型1.1 class类1.2 class继承1.3 class类成员可见性1.4 readonly1.5 类型兼容性1.5.1 对象之间的类型兼容性1.5.2 接口之间类型兼容性1.5.3 函数之间类型兼容性1.6 交叉类型1.7 交叉类型(&)和继承(extends)的对比二、泛型2.1 泛型约束--指定更具…...

如何远程控制电脑?您只需要这样做
案例:在外面怎么远程控制电脑? “我学校教室有电脑,但我每次上课的时候还是需要带自己的电脑(好重!),只因为有些资料只在自己的电脑上。听说远程控制电脑可以解决这个问题,那如何远…...

【51单片机】:LED任务及汇编解释任务
学习目标: 1、用汇编或者c语言实现D1 D3 D5 D7 为一组 ;D2 D4 D6 D8 为一组 ,两组实现 1)一组亮约一秒 另一组灭一秒,这样的互闪现象五次后 25分 2)所有灯灭约一秒后, …...

从生活习惯到肠道微生物,揭秘胃肠道癌症的成因
谷禾健康 编辑 癌症一直是全球人类关注的重点,近年来癌症的发病率迅速增加,例如乳腺癌、前列腺癌和肺癌非常普遍。胃肠道癌在发病率和死亡率方面位居首位,并造成重大的社会经济负担。 胃肠道癌症包括胃癌、肝癌、食道癌、胰腺癌和结直肠癌等…...

八十行代码实现开源的 Midjourney、Stable Diffusion “咒语”作图工具
本篇文章聊聊如何通过 Docker 和八十行左右的 Python 代码,实现一款类似 Midjourney 官方图片解析功能 Describe 的 Prompt 工具。 让你在玩 Midjourney、Stable Diffusion 这类模型时,不再为生成 Prompt 描述挠头。 写在前面 本文将提供两个版本的工…...
Redis为什么这么快
RedisRedis为什么这么快基于内存单线程实现(Redis 6.0 以前)IO多路复用模型高效的数据结构Redis为何选择单线程Redis的应用场景Redis怎么实现消息队列Redis的主从复制原理主从复制的原理过期键的删除策略Redis为什么这么快 基于内存 Redis是使用内存存…...
JayDeBeApi对数据类型的支持
JayDeBeApi对数据类型的支持 常用的数据类型如下: 字符类型 内置字符类型包括:char, nchar, varchar, nvarchar 和lvarchar CHARACTER(n) 和 CHARACTER VARYING(n)这样的别名同样支持 参考代码:test_string_type.py create ""&…...

一文盘点 Zebec 生态几大利好,让 ZBC 近期“狂飙”
近期,ZBC通证迎来了新一轮上涨趋势,我们看到其从3月11日左右的低点$0.0115上涨至$0.0175,这也是近期的最大涨幅之一。我们看到,推动ZBC上涨的主要因素,是Zebec生态近期频繁的布局所带来的系列利好推动。 本文将对近期的…...

【数据结构】栈和队列(笔记总结)
👦个人主页:Weraphael ✍🏻作者简介:目前学习C和算法 ✈️专栏:数据结构 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&…...
【Java】自定义注解和AOP切面的使用
前言 我们在开发的过程中,一般都需要对方法的入参进行打印,或者Debug调试的时候我们要查看方法入参的参数是否数量和数据正确性。 一般我们需要知道请求的参数、接口路径、请求ip等 但是考虑以后项目上线BUG排查的问题,最好的方式就是使用…...

前后台协议联调拦截器
前后台协议联调&拦截器4,前后台协议联调4.1 环境准备4.2 列表功能4.3 添加功能4.4 添加功能状态处理4.5 修改功能4.6 删除功能5,拦截器5.1 拦截器概念5.2 拦截器入门案例5.2.1 环境准备5.2.2 拦截器开发步骤1:创建拦截器类步骤2:配置拦截器类步骤3:S…...

【还在传统绑骨骼动画?】让AI助力你实现2D游戏角色动画流程
思路(让3D模型替代动作) 一、利用MJ或者SD生成你需要的游戏角色(获取原图像) 需要的知识: 会调关键词chatGpt(看小红书、抖音、B站、Youtube、Telegrame等等都行,别傻忽忽跑到知识星球被收割…...
动态规划+例题
适用场景 题目链接:数字三角形 /*正推DP,可能数据比较小,这个正推不太麻烦可以AC*/ #include<bits/stdc.h> using namespace std; int r; int a[1005][1005],f[1005][1005];int main(){cin>>r;for(int i1;i<r;i){for(int j1…...

快商通荣获多个政府科技、人才奖项
近日,快商通与快商通首席科学家李海洲教授荣获由厦门市科学技术局、厦门市委人才办等多部门发布的“2022年度厦门市科学技术奖”、“2022厦门十大成长性人才企业”、“2022厦门战略性新兴产业十大创新人才”等多个 政府科技、人才奖项 ,并进行全网公示。…...

Linux的基本命令的使用
文章目录一、初识LinuxLinux目录结构二、如何拥有一个Linux环境?三、Linux命名Linux命令基础lscd pwd特殊路径符clearmkdirtouch cat morecp mv rmsuwhich findgrep wc 管道符ehco tail 重定向符psnetstatvi vim一、初识Linux 我们的计算机由硬件和软件两部分组成&…...
RecycleView小结
RecycleView四级缓存 一级缓存:用于存放当前屏幕可显示区域的ViewHolder,目的是为了方便更新数据,以及对View操作时更加快捷二级缓存:用于缓存最近滑动出屏幕的ViewHolder,目的是为了当用户将该View滑出屏幕外时又突然…...

【Python】如何实现Redis构造简易客户端(教程在这)
文章目录前言一、准备二、原理剖析三、编写简易Redis客户端总结前言 Redis 是我们在开发过程中经常会用到的内存数据库,尤其是在Python的第三方模块Redis-py的支持下,在Python中使用Redis及其方便。 但是在有些情况下,我们无法使用像Redis-…...

326. 3 的幂 ——【Leetcode每日一题】
326. 3 的幂 给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。 整数 n 是 3 的幂次方需满足:存在整数 x 使得 n3xn 3^xn3x。 示例 1: 输入:n 27 …...

UE4 Sequence学习
1.常用轨道 1.1 Camera轨道 Camera轨道可以理解为Camera Cuts轨道和Camera Actor轨道,一般点击Sequencer上的摄像机图标可以自动创建: Camera Cuts轨道,可以进行不同相机机位的切换,一般会随着Camera Actor轨道自动创建&#x…...

总结MySQL、Redis的优化措施与使用 mysql_upgrade升级数据结构
目录 一.MySQL数据库优化 二.Redis优化 三.MySQL创建测试账号报错 一.MySQL数据库优化 遵循MySQL层优化的五个原则: 减少数据访问,返回更少的数据,减少交互次数减少服务器CPU开销,利用更多资源。理解SQL优化原理并进行SQL优化,…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
「Java基本语法」变量的使用
变量定义 变量是程序中存储数据的容器,用于保存可变的数据值。在Java中,变量必须先声明后使用,声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例:声明与初始化 public class VariableDemo {publi…...