Loading

TypeScript学习笔记

第一个TS文件

步骤

安装解析TypeScript工具包

npm i -g typescript

新建一个ts文件

hello.ts,内容如下

console.log('Hello TS')

执行代码

分为两步:

1.ts代码->js代码,在当前目录打开终端,输入命令:tsc hello.ts,会生成一个同名的hello.js文件

tsc hello.ts

2.执行js代码

node hello.js

简化执行TS的步骤

每次修改完代码都要重复执行上述两个命令才能执行,比较繁琐。

简化方式:使用 ts-node 包,直接在Node.js中执行TS代码

安装命令:

npm i -g ts-node

使用方式:

ts-node hello.ts

注释和输出语句

注释

注释有两种形式:单行注释和多行注释

1.单行注释 快捷键:Ctrl + /

// 这是一行注释

2.多行注释 快捷键:Shift + Alt + a

/**
 * 这是第一行注释
 * 这是第二行注释
 */

输出语句

console.log('Hello TS')

变量

基本使用

1.声明变量并指定类型

let age: number;
  • let 是TS中的关键字,用来声明变量
  • age 是定义的变量名称
  • : number 用来指定变量age为数值类型
  • 注意:分号是可选的

2.给变量赋值

age = 18
  • 使用 = 完成变量赋值

注意:当用let声明一个变量,它使用的是词法作用域或块作用域。不同于使用var声明的变量那样可以在包含它们的函数外访问,块作用域变量在包含它们的块或for循环之外是不能访问的。

简化方式

声明变量的同时就赋值

let age: number = 20

类型注解

类型注解:是一种为变量添加类型约束的方式。

约定了什么类型,就只能给变量赋什么类型的值。

变量的命名规则

变量名称只能出现:数字,字母,下划线(_),美元符号($),并且不能以数字开头。

注意:变量名称区分大小写

变量的命名规范

推荐:变量名称要有意义,使用驼峰命名法(首字母小写,后面每个单词首字母大写)

基础类型

TypeScript中的数据类型分为两大类:

1.基本数据类型

常见的基本数据类型有5个:

number/string/boolean/undefined/null

2.对象类型(复杂数据类型)

数字类型

数字类型:包含整数值和浮点型(小数)值

// 整数
let size: number = 18
// 小数
let score: number = 99.9

console.log(size)
console.log(score)

// 正数
let salary: number = +1000
// 负数
let salary1:number = -2000

console.log(salary)
console.log(salary1)

字符串类型

  • 字符串:由零个或多个字符串联而成的,用来表示文本信息。

  • 字符串可以使用单引号或双引号,推荐使用:单引号

// 空字符串
console.log('')

console.log('Hello TS')
console.log("Hello TS")
  • 字符串类型的类型注解:string,声明变量时要添加类型注解
// 声明字符串类型的变量
let animal: string = '小狗'
console.log(animal)

布尔类型

布尔类型,用来表示真或假

只有两个值,分别是:true和false。

布尔类型的注解为:boolean

// 真
let isStudying: boolean = true 
// 假
let isPlayingGame: boolean = false

console.log(isStudying)
console.log(isPlayingGame)

undefined、null

共同特点:只有一个值,值为类型本身

undefined 类型的值为:undefined,表示声明但未赋值的变量值。

null 类型的值为:null,表示声明了变量并已赋值,值为null。

// undefined
let u: undefined = undefined

// null
let n: null = null

console.log(u)  // undefined
console.log(n)  // null

let u1: undefined
console.log(u1)  // undefined

数组

数组就是存放多个数据的集合,可以存储任意多个数据。

注意:数组中通常都是相同类型的数据。

创建数组

创建数组有两种方式:

语法一(推荐):

let names: string[] = []

[]表示数组,如果数组中没有内容,就是一个空数组。

数组中的类型注解由两部分组成:类型+[],上述表示字符串类型的数组。

多个元素之间使用逗号分隔(,)

let names: string[] = ['啦啦啦', '略略略', '哒哒哒']
console.log(names)  // [ '啦啦啦', '略略略', '哒哒哒' ]

语法二(不推荐):

let names: string[] = new Array()

数组中有数据时:

let names: string[] = new Array('啦啦啦','略略略','哒哒哒')

数组的长度

数组长度:表示数组中元素的个数,通过数组的length属性来获取。

//数组长度
let names: string[] = ['啦','略','哒']
console.log(names.length) // 3

数组索引

数组中的每个元素都有自己的序号。

我们把数组中元素的序号,称为索引(下标),数组中的元素与索引一一对应。

注意:索引是从0开始的。

存值和取值

取值

从数组中,获取到某一个元素的值,就是从数组中取值。

可以通过索引获取到某一个元素的值。

语法:

数组名称[索引]
let foods: string[] = ['啦1','啦2','啦3']
//取值
console.log(foods[0])  // 啦1

存值

如果要修改数组中某个元素的值,就要用到数组存值。

技巧:要先获取到要修改的元素,再存值。

let foods: string[] = ['啦1','啦2','啦3']
foods[1] = '略2'
console.log(foods)  // [ '啦1', '略2', '啦3' ]

添加元素

根据索引是否存在,有两种功能,1.修改元素,2.添加元素

1.如果索引存在,就表示:修改元素

2.如果索引不存在,就表示添加元素。

let foods: string[] = ['啦1','啦2','啦3']
foods[3] = '啦4'
console.log(foods)

foods[foods.length] = '啦5'
console.log(foods)

遍历数组

遍历数组:就是依次获取数组中的数据

let nums: number[] = [100,200,300]
//使用for循环遍历数组,取出数组中的每一项元素。
for(let i:number = 0;i <= nums.length-1; i++){
    console.log(nums[i])
}  

练习:求数组中所有元素的和

let nums: number[] = [200, 100, 300]
let sum: number = 0

for (let i: number = 0; i < nums.length; i++) {
    sum += nums[i]
}
console.log(sum)

练习:找出数组中的最大值

let nums1: number[] = [1, 9, 12, 3, 6]

let max: number = nums1[0]
for (let i: number = 1; i < nums1.length; i++) {
    if (nums1[i] > max) {
        max = nums1[i]
    }
}
console.log(max)

练习:找出数组中不为0的元素

let nums: number[] = [5, 3, 0, 7, 9, 0, 14]

let newArr: number[] = []
for (let i: number = 0; i < nums.length; i++) {
    if(nums[i] !== 0){
        newArr[newArr.length] = nums[i]
    }
}
console.log(newArr)

元组

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 stringnumber类型的元组。

const teacherInfo: [string, number] = ["zhangsan", 18];

高级类型

联合类型

联合类型表示一个值可以是几种类型之一。 我们用竖线( |)分隔每个类型,所以 number | string | boolean表示一个值可以是 numberstring,或 boolean

const arr: (number | string)[] = [1, "2", 3];

如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。

interface Bird {
  fly: boolean;
  sing: () => {};
}
interface Dog {
  fly: boolean;
  bark: () => {};
}

function trainAnimal(animal: Bird | Dog) {
  animal.fly; 
  animal.sing(); //error
}

类型保护

使用类型断言

interface Bird {
  fly: boolean;
  sing: () => {};
}

interface Dog {
  fly: boolean;
  bark: () => {};
}

//采用类型断言的方式进行类型保护
function trainAnimal(animal: Bird | Dog) {
  if (animal.fly) {
    (animal as Bird).sing();
  } else {
    (animal as Dog).bark();
  }
}

in 语法来做类型保护

interface Bird {
  fly: boolean;
  sing: () => {};
}

interface Dog {
  fly: boolean;
  bark: () => {};
}
//in 语法来做类型保护
function trainAnimalSecond(animal: Bird | Dog) {
  if ('sing' in animal) {
    animal.sing();
  } else {
    animal.bark();
  }
}

typeof语法来做类型保护

//typeof语法来做类型保护
function add(first: string | number, second: string | number) {
  if (typeof first === 'string' || typeof second === 'string') {
    return `${first}${second}`;
  } else {
    return first + second;
  }
}

使用instanceof来做类型保护

//使用instanceof来做类型保护
//注意:只有使用类定义,才能有instanceof,不能使用interface。
class NumberObj {
  count: number;
}
function addSecond(first: object | NumberObj, second: object | NumberObj) {
  if (first instanceof NumberObj && second instanceof NumberObj) {
    return first.count + second.count;
  }
  return 0;
}

运算符

常用的运算符:

  • 算术运算符

  • 赋值运算符

  • 递增/递减运算符

  • 比较运算符

  • 逻辑运算符

算术运算符

算术运算符包含:加(+),减(-), 乘(*), 除(/)

用来实现两个数值之间的计算

console.log(1+2)  // 3
console.log(2-1)  // 1

console.log(1*2) // 2
console.log(1/2) // 0.5

加号的其他作用

加号可以实现字符串拼接。

// 字符串拼接
console.log('周' + '杰伦') // 周杰伦
console.log(1 + '2') // 12

注意:除加号之外,其他算术运算符只应该和数字类型一起使用。

在字符串前面添加 + 号,可以将字符串类型转为数字类型(字符串内容为数字时才有意义)

console.log(2 - +'1')
// +'1' 表示将 '1'(string) => 1(number)

赋值运算符

赋值运算符:将等号右边的值赋值给它左边的变量

let age: number = 18

// age = age + 1
// 简化形式
age += 1

console.log(age)

自增和自减运算符

自增(++)运算符是 +=1 的简化形式,自减(--)是 -=1 的简化形式。

let age: number = 18
age++
console.log(age)

比较运算符

比较运算符:用于比较两个数据的值,并返回其比较的结果,结果为布尔类型。

比较运算符包含6个:

  • 大于(>)
  • 大于等于(>=)
  • 小于(<)
  • 小于等于(<=)
  • 等于(===)
  • 不等于(!==)

注意:比较运算符常用于数字类型的比较。

逻辑运算符

逻辑运算符:与,或,非

逻辑运算符通常用于布尔类型的计算,并且结果也是布尔类型。

  • 与(逻辑与),用 && 符号来表示。当 && 两边的值同时为 true 时,结果才为true,否则为false。
console.log(true && false)  // false
console.log(2 > 1 && 2 >= 2)  // true
  • 或(逻辑或),用 || 符号来表示。当 || 两边的值只要有一个为true,结果就为true,否则,为false。
console.log(true || false)  //true
console.log(3 < 2 || 1 <= 2)  //true
  • 非(逻辑非),符号为 !。表示取反,即:true->false,而false->true
console.log(!true)  // false
console.log(!false || false) //true

语句

条件语句

条件语句:根据判断条件的结果(真或假),来执行不同的代码,从而实现不同的功能。

if语句

在TypeScript中if语句就是实现条件判断的

if语句的语法

if(判断条件){
    条件满足时,要做的事情
}
  • 判断条件: 布尔类型(true或false)

else语句

在TypeScript中else语句必须配合if语句来使用。

else语句表示:条件不满足,要做的事情。

else语句的语法

if(判断条件){
    条件满足时,要做的事情
}else{
    条件不满足时,要做的事情
}

三元运算符

三元运算符的作用与if...else语句类似,根据判断条件的真假,得到不同的结果。

语法:

结果 = 判断条件 ? 值1 : 值2
  • 如果判断条件为真,结果为 值1
  • 否则,判断条件为假,结果为 值2
let result: String = 5 > 3 ? '大于' : '小于'
console.log(result)  // 大于

注意:得到结果的类型由值1和值2的类型决定(值1和值2的类型相同)

循环语句

for循环

语法:

for(初始化语句; 判断条件; 计数器更新){
	循环体
}
  • 初始化语句:声明计数器变量,记录循环次数。
  • 判断条件:判断循环次数是否达到目标次数。
  • 计数器更新:计数器数量加1。
  • 循环体:重复执行的代码,也就是重复做的事情
for(let i:number = 1; i <= 3; i++){
    console.log('啦啦啦啦啊')
}

break和continue

break和continue常用在循环语句中,用来改变循环的执行过程

break 能够让循环提前结果(中止循环)

for(let i: number = 1; i<=5; i++){
    if(i === 4){
        break
    }
    console.log('正在吃第'+i+'个包子')
}

continue能够让循环间断执行(跳过本次循环,继续下一次循环)

for(let i: number = 1; i<=5; i++){
    if(i === 3){
        continue
    }
    console.log('正在吃第'+i+'个包子')
}

输入内容如下:

正在吃第1个包子
正在吃第2个包子
正在吃第4个包子
正在吃第5个包子

函数

函数概述

使用函数来封装相似的代码,在需要的时候调用函数,相似的代码不在需要重复编写。

函数的使用

函数的使用分为两步:1.声明函数 2.调用函数

1.第一步:声明函数

function 函数名称(){
    函数体
}

2.第二步:调用函数

函数名称()

注意:只有调用函数后,函数中的代码才会执行。

例如:

// 1.声明函数
function sing(){
    console.log('啦啦啦!啦啦啦!')
}
// 2.调用函数
sing()

函数的使用练习:计算两个变量的和

//1.创建函数
function sum() {
    //2.函数体中计算两个变量的和
    let num1: number = 10
    let num2: number = 20
    let result: number = num1+num2
    console.log(result)
}
//3.调用函数
sum()

函数的参数

概述

函数参数的作用:增加了函数的灵活性,通用性。针对相同的功能,能够适应更多的数据。

function sing(songName:string){
    console.log(songName)
}
sing('啦啦啦!')
sing('哒哒哒!')

形参和实参

函数参数分为两部分:形参和实参

1.形参:声明函数时指定的参数,放在声明函数的小括号中。

function sing(songName: string){ }

语法:

形参名称: 类型注解

2.实参:调用函数时传入的参数,放在调用函数的小括号中。

sing('啦啦啦,啊啊啊')

其他说明:

(1)根据具体的功能,函数参数可以有多个,参数之间用逗号(,)来分隔。

(2)实参和形参按照顺序一一对应。

(3)实参必须符合形参的类型要求,否则会报错。

function fn(name: string, age: number) {
    console.log('1 ' + name)
    console.log('2 ' + age)
}
fn('啦啦啊', 18)

可选参数和默认参数

在TypeScript里我们可以在参数名旁使用 ? 实现可选参数的功能。

function buildName(firstName: string, lastName?: string) {
  if (lastName) return firstName + " " + lastName;
  else return firstName;
}

let result1 = buildName("Bob");
let result3 = buildName("Bob", "Adams");

let result2 = buildName("Bob", "Adams", "Sr."); // error

可选参数必须跟在必须参数后面。 如果上例我们想让first name是可选的,那么就必须调整它们的位置,把first name放在后面。

在TypeScript里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是undefined时。 它们叫做有默认初始化值的参数。

function buildName(firstName: string, lastName = "Smith") {
  console.log(firstName + " " + lastName);
  return firstName + " " + lastName;
}

let result1 = buildName("Bob"); //Bob Smith
let result2 = buildName("Bob", undefined); //Bob Smith
let result4 = buildName("Bob", "Adams"); //Bob Adams
// let result3 = buildName("Bob", "Adams", "Sr."); //error

剩余参数

在JavaScript里,你可以使用 arguments来访问所有传入的参数。

在TypeScript里,你可以把所有参数收集到一个变量里。

function buildName(firstName: string, ...restOfName: string[]) {
  console.log(restOfName); //[ 'bbb', 'ccc', 'ddd' ]
  console.log(firstName + " " + restOfName.join(" ")); //[ 'bbb', 'ccc', 'ddd' ]
  return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("aaa", "bbb", "ccc", "ddd");

函数的返回值

概述

函数返回值的作用:将函数内部计算的结果返回,以便于使用该结果继续参与其他的计算。

例如:

function getSum(nums: number[]): number {
    let sum: number = 0
    for (let i: number = 0; i < nums.length; i++) {
        sum += nums[i]
    }
    return sum
}

let result: number = getSum([1,2,3])+ getSum([1,3,5])
console.log(result) // 15

基本使用

步骤:1.指定返回值类型 2.指定返回值

1.指定返回值类型

function fn(): 类型注解{
    
}
  • 在声明函数的小括号后面,通过 : 类型注解 指定
function fn(): string{
    
}

2.指定返回值

function fn(): 类型注解{
    return 返回值
}
  • 在函数体中,使用 return 关键字来返回函数执行的结果

注意:返回值必须符合返回值类型的类型要求,否则会报错

3.使用变量接受函数返回值

let result: 类型注解 = fn()

注意:变量的类型要与函数的返回值类型一致。

return的说明

1.将函数内部的计算结果返回。

2.return后面的代码不会执行。

3.return只能在函数中使用,否则会报错。

4.return可以单独使用,用来刻意中止函数的执行。

function play(age: number):void {
    if (age < 18) {
        return
    }
    console.log('啦啦啦')
}
play(17)

注意:如果函数没有返回值,默认返回值类型是void(空),可以省略不写。

变量的作用域

变量的作用域:代码中定义变量的区域,它决定了变量的使用范围

在TS或者JS中,函数可以形成作用域,叫做:函数作用域

根据范围的不同,变量可以分为两种:1.局部变量 2.全局变量

  • 局部变量:表示在函数内部声明的变量,该变量只能在函数内部使用
function fn() {
    let num: number = 1
    console.log(num) //此处可以访问到变量num
}
fn()
console.log(num) //此处不能访问到变量num
  • 全局变量:表示在函数外部声明的变量,该变量在当前ts文件的任何地方都可以使用。
let num: number = 1
function fn() {
    console.log(num) //此处可以访问到变量num
}
fn()
console.log(num) //此处可以访问到变量num

对象

TS对象:一组相关属性和方法的集合,并且是无序的。

创建对象

对象的语法:

let persion = {}

此处的{}表示对象,而对象中没有属性或方法时,称为空对象。

对象中的属性或方法,采用键值对的形式,键、值之间使用冒号(:)来配对。

let persion = {
    键1: 值1,
    键2: 值2
}

例如:

let persion = {
    name: '周老师',
    age: 20,
    sayHi: function () {
        console.log('大家好!')
    }
}

内置对象

内置对象是JS/TS自带的一些基础对象,提供了TS开发时所需的基础和必要的能力。

数组对象

数组是TS中最常用、最重要的内置对象。

数组的常用操作:添加、删除、遍历、过滤等。

重点:1.属性(length) 2.方法(push、forEach、some)

length属性:获取数组长度

let songs: string[] = ['啦啦啦1', '啦啦啦2', '啦啦啦3']
console.log(songs.length)

数组对象-push

push方法:添加元素(在数组最后一项元素的后面添加)。

let songs: string[] = ['啦啦啦1', '啦啦啦2', '啦啦啦3']
console.log(songs.length)
let len: number = songs.push('哒哒哒')
console.log(songs, len)

数组对象-forEach

forEach方法:遍历数组

let songs: string[] = ['啦1', '啦2', '啦3']
//使用forEach方法遍历数组
songs.forEach(function (item, index) {
    console.log('索引为', index, '元素为', item)
})

注意:此处的回调函数,是作为forEach方法的实参传入,不应该指定类型注解。

数组对象-some

some方法:遍历数组,查找是否有一个满足条件的元素(如果有,就可以停止循环)

let nums: number[] = [1, 12, 8, 9, 6]
nums.some(function (num) {
    console.log(num)
    if (num > 10) {
        //说明已经找到满足条件的元素,通过返回true来停止后续的循环
        return true
    }
    //说明没有找到满足条件的元素
    return false
})

some方法的返回值:布尔值,如果找到满足条件的元素,结果为true,否则,为false

class People {
  content = 'Hi everyone!';
  sayHello() {
    return this.content;
  }
}

const zs = new People();
console.log(zs.sayHello());

继承

使用继承来扩展现有的类。

class Anmial {
  content = 'Hi everyone!';
  sayHello() {
    return this.content;
  }
}

class Dog extends Anmial {
  sayLove() {
    return 'I love you';
  }
}

const zs = new Dog();
console.log(zs.sayHello());
console.log(zs.sayLove());

super关键字

在typescript中提供了一个关键字super指向父类,super.方法名()就可以调用父类同名的方法。

class Anmial {
  content = 'Hi everyone!';
  sayHello() {
    return this.content;
  }
}

class Dog extends Anmial {
  sayHello() {
    return super.sayHello() + ',你好';
  }
  sayLove() {
    return 'I love you';
  }
}

const zs = new Dog();
console.log(zs.sayHello());
console.log(zs.sayLove());

接口

对象的类型注解

语法说明:

let persion:{
    name: string;
    age: number;
}

对象的类型注解的语法类似于对象自身的语法

注意:键值对中的值是类型,多个键值对之间使用分号(;)分隔。

//此处的{}表示对象的类型注解
let person: {
    name: string;
    age: number
}
//此处的{}表示ts中的对象
person = {
    name: '啦老师',
    age: 18
}

对象方法的类型注解

let p1: {
    sayHi: () => void
}
p1 = {
    sayHi: function (){
        console.log('哎呦不错哦!')
    }
}

let p2:{
    sing: (name: string) => void
}
p2 = {
    sing: function (name: string){
        console.log('歌曲名称:' + name)
    }
}

let p3: {
    sum: (num1: number, num2: number) => number
}
p3 = {
    sum: function(num1: number, num2: number){
        return num1 + num2
    }
}

接口的使用

直接在对象名称后面写类型注解的坏处:1.代码结构不简洁 2.无法复用类型注解。

接口:为对象的类型注解命名,并为你的代码建立契约来约束对象的结构

语法:

interface IUser{
    name: string
    age: number
}

interface 表示接口,接口名称约定以I开头。

推荐:使用接口来作为对象的类型注解。

例如:

//创建一个接口
interface IUser{
    name: string
    age: number
    sayHi: () => void
}

//使用接口
let p1: IUser = {
    name: 'jack',
    age: 18,
    sayHi: function(){
        console.log('hello,杰克')
    }
}

接口可以存任意类型

例如:

interface Person {
  name: string;
  age?: number;
  [propName: string]: any; //表示属性名是字符串类型,属性值是任意类型
}

取值和存值

取值

取值:

即拿到对象中的属性或方法并使用。获取对象中的属性,称为:访问属性。获取对象中的方法并调用,称为:方法调用。

  • 访问属性
let jay = {name: '周杰伦', height: 175}
console.log(jay.name) // 通过.就可以访问对象中的属性。

示例:

//创建一个接口
interface IUser{
    name: string
    height: number
}

//创建对象
let jay: IUser = {
    name: '周杰伦',
    height: 175
}
// 访问对象jay的name属性
console.log(jay.name)
console.log(jay.height)
  • 调用方法
let jay = {
    sing: function () {
        console.log('啦啦啦~')
    }
}
jay.sing()

示例:

//创建一个接口
interface IUser{
    name: string
    height: number
    sing: () => void
}

//创建对象
let jay: IUser = {
    name: '周杰伦',
    height: 175,
    sing: function () {
        console.log('故事的小黄花~')
    }
}
// 访问对象jay的name属性
console.log(jay.name)
console.log(jay.height)
//调用方法
jay.sing()

补充说明

console.log(参数1, 参数2, ...)

log方法可以有多个参数。

console.log('我叫', jay.name)

存值

存值,即修改对象中属性的值。

interface IUser{
    name: string
    height: number
}

let jay: IUser = {
    name: '周杰伦',
    height: 175
}

//修改name属性的值
jay.name = '周董'
console.log(jay.name)

枚举

使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。

创建枚举的语法

enum 枚举名称{成员1, 成员2, ...}

示例:

enum Gender{Female, Male}
enum Player{X, O}

注意:枚举中的成员,根据功能自己指定!当变量的值,只能是几个固定值中的一个,应该使用枚举来实现。

枚举是一种类型,因此,可以作为变量的类型注解。

enum Gender{
     Female,
     Male
}
//创建变量,使用枚举作为类型
let userGender: Gender = Gender.Female
console.log(userGender) // 0
console.log(Gender.Female)  //0
console.log(Gender.Male) //1 

注意:枚举成员是只读的,也就是说枚举的成员可以访问,但是不能赋值。

枚举成员是有值的,默认为:从0开始自增的数值

enum Status {
  OFFLINE,
  ONLINE,
  DELETED,
}
console.log(Status.OFFLINE); //0
console.log(Status.ONLINE); //1
console.log(Status.DELETED); //2

数字枚举

我们把枚举成员的值为数字的枚举,称为:数字枚举

当然,也可以给枚举中的成员初始化值,其他的值会从初始化的值开始增长,如下A为101

enum Gender{
     Female = 1,
     Male = 100,
     A
}
//创建变量,使用枚举作为类型
let userGender: Gender = Gender.Female

console.log(Gender.Female)  //1
console.log(Gender.Male) //100
console.log(Gender.A)  //101

字符串枚举

字符串枚举:枚举成员的值是字符串。

enum Gender {
    Female = '女', 
    Male = '男'
}

注意:字符串枚举没有自增长行为,因此,每个成员必须有初始值。

反向映射

除了创建一个以属性名做为对象成员的对象之外,数字枚举成员还具有了反向映射,从枚举值到枚举名字。

enum Status {
  OFFLINE,
  ONLINE,
  DELETED,
}
console.log(Status[0]); //OFFLINE
console.log(Status[3]); //undefined

泛型

使用泛型可以来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件

函数泛型

function join<T>(first: T, second: T) {
  return `${first}${second}`;
}
join<number>(1, 2);

function map<T, P>(first: T, second: P) {
  return `${first}${second}`;
}
map<number, string>(1, '2');
// map(1, '2'); //可以自动推断

//返回的结果同样可以使用泛型
function anotherJoin<T>(first: T, second: T): T {
  return first;
}

//T类型的数组
function loggingIdentity<T>(arg: T[]): T[] {
  console.log(arg); //[ 'abc' ]
  console.log(arg.length); // 1
  return arg;
}
loggingIdentity<string>(['abc']);

泛型类型

使用泛型定义函数本身的类型

function hello<T>(param: T) {
  return param;
}
const func: <T>(param: T) => T = hello;

泛型类

class DataManager<T> {
  constructor(private data: T[]) {}
  getItem(index: number): T {
    return this.data[index];
  }
}
const data = new DataManager<number>([1]);
data.getItem(0);

泛型接口

泛型约束

定义一个接口来描述约束条件,

interface Item {
  name: string;
}
class DataManager<T extends Item> {
  constructor(private data: T[]) {}
  getItem(index: number): string {
    return this.data[index].name;
  }
}
//需要传入符合约束类型的值,包含必须的属性
const data = new DataManager([
  {
    name: 'zs',
  },
]);
posted @ 2022-06-20 14:20  charlatte  阅读(37)  评论(0编辑  收藏  举报