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优化,…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
