TypeScript基础
TypeScript的基本使用
安装TypeScript包
1 | npm i -g typescript |
解释:全局安装typescript包
1 | //hello.ts |
将ts文件转化为js文件
1 | tsc hello.ts |
此时当前目录中会生成一个hello.js文件
执行
1 | node hello.js |
注意:在执行的时候,执行的是
js
文件
简化执行TS的步骤
使用ts-node包,可以直接在Node.js中执行TS代码
原理:其实就是借助这个包将上面的步骤简化为一个步骤
全局安装
ts-node
1 | npm i -g ts-node |
ts-node包的使用
1 | ts-node hello.ts |
注意这里执行的是ts文件,而且这里将不再生成新的
hello.js
,可以直接输出js执行的结果
变量的基本使用
声明变量并指定类型
1
let age: number;
给变量赋值
1
2
3age = 18
//声明时就赋初值
let age: number = 18
类型注解
作用:是一种为变量添加类型约束的方式
也就是说在声明时指定了变量是什么类型,那么在后面使用该变量的时候就只能时指定的类型
TypeScript中常用的数据类型
- number:包含整数类型和浮点数类型
- string
- boolean
- undefined
- null
创建数组的两个语法形式
1 | let name: string[] = [] |
推荐使用
1 | let names: string[] = new Array() |
向数组中添加元素
1 | name[name.length] = 'ddd' |
如果索引不存在,就表示:添加元素
函数的使用
1 | function fn(name: string, age: number) { |
上面的函数没有返回值
注意:如果没有指定函数的返回值,那么,函数返回值的默认类型为void(空)
1 | function getSum(nums: number[]): number { |
此处介绍的是有返回值函数的使用,以及返回值的接收
注意: 变量
result
的类型与函数getSum
的返回值类型要一致
函数整体指定类型的方式
1
2
3
4
5
6
7
8 const sum: (num1: number, num2: number) => number = function(num1, num2) {
return num1 + num2;
}
//或者
type TSum = (num1: number, num2: number) => number;
const sum: TSum = function(num1, num2) {
return num1 + num2;
}
调试函数
修改launch.json中的相关配置
1 | { |
对象的类型注解
TS中的对象是结构化的,结构简单来说就是对象有什么属性或方法。再使用对象前,就可以根据需求,提前设计号对象的结构。比如创建一个对象,包含姓名、年龄两个属性。
1 | let person: { |
对象方法的类型注解
技巧:鼠标放在变量名称上,VSCode就会给出该变量的类型注解。
1 | let person: { |
接口的使用
直接在对象名称后面写类型注解的坏处:
- 代码结构不简洁
- 无法复用类型注解
接口:为对象的类型注解命名,并为代码建立契约来约束对象的结构
语法:
1 | interface IUser { |
interface表示接口,接口名称约定以
I
开头。推荐:使用接口来作为对象的类型注解
浏览器中运行TS
注意:浏览器中只能运行JS,无法直接运行TS,因此,需要将TS转化为JS然后再运行
浏览器中运行TS的步骤:
- 使用命令tsc index.ts将ts文件转化为js文件
- 在页面中,使用script标签引入生成的js文件(注意是js文件)
1 | <script src="./index.js"></script> |
问题:每次修改ts文件后,都要重新运行tsc命令将ts文件转化为js文件
解决方法:使用tsc命令的监视模式
1 | tsc --watch index.ts |
解释:–watch表示启用监视模式,只要重新保存了ts文件,就会自动调用tsc将ts文件转化为js文件
字符串字面量类型组成的联合类型
1 | type TDirection = 'UP' | 'RIGHT' | 'DOWN' | 'LEFT' |
**tip:**在f12中选中某个元素,然后在控制台中通过$0.__proto__来获取该元素的类型
TS的类型推论
在TS中,某些没有明确指出类型的地方,类型推论会帮助提供类型。
换句话说:由于类型推论的存在,一些地方,类型注解可以省略不写!
发生类型推论的2中常见场景:
- 声明变量并初始化时
- 决定函数返回值时
1 | let num |
1 | let num = 12 |
类型断言
问题:调用
querySelector()
通过id选择器获取DOM元素时,拿到的元素类型都是Element
因为无法根据id来确定元素的类型,所以,该方法就返回了一个宽泛的类型:元素(Element)类型
不管是h1还是img都是元素
导致新问题:无法访问img元素的src属性了
因为:Element类型只包含所有元素共有的属性和方法(比如:id属性)
解决方法:使用类型断言,来手动指定更加具体的类型(比如,此处应该比Element类型更加具体)
语法:
1 值 as 更具体的类型比如:
1 let img = document.querySelector('#image') as HTMLImageElement解释:我们确定id=”image”的元素是图片元素,所以,我们将类型指定为HTMLImageElement
总结:
类型断言:手动指定更加具体(精确)的类型
使用场景:当你比TS更了解某个值的类型,并且需要指定更具体的类型时
1
2
3
4
5 //document.querySelector() 方法的返回值类型为:Element
//如果是 h1 标签
let title = document.querySelector('#title') as HTMLHeadingElement
//如果是 img 标签
let image = document.querySelector('#image') as HTMLImageElement技巧:通过console.dir()打印DOM对象,来查看该元素的类型
枚举
使用变量时存在的问题:例如:
变量的类型是string,它的值可以是任意字符串
如果不小心写错了,代码不会报错,但功能就无法实现了,并且很难找错。
也就是:string类型的变量,取值太宽泛,无法很好的限制值
枚举是组织有关联数据的一种方式
使用场景:当变量的值,只能是几个固定值中的一个,应该使用枚举来实现
注意:JS中没有枚举,这是TS为了弥补JS自身不足而新增的
创建枚举的语法:
1 | enum 枚举名称 { 成员1, 成员2, ... } |
示例:
1 | enum Gender { Female, Male } |
约定枚举名称、成员名称以大写字母开头
多个成员之间使用逗号(,)分隔
注意:枚举中的成员,根据功能自己指定!
注意:枚举中的成员不是键值对!
使用枚举:
枚举是一种类型,因此,可以作为变量的类型注解
1 | enum Gender { Female, Male } |
访问枚举(Gender)中的成员,作为变量(userGender)的值:
1 | userGender = Gender.Female |
问题:将枚举成员赋值给变量,变量的值是什么?
1 | enum Gender { Female, Male } |
枚举成员是有值的,默认为:从0喀什自增的数值
我们把枚举成员的值为数字的枚举,称为:数字枚举
当然,也可以给枚举中的成员初始化值
1 | enum Gender { Female = 1, Male } // Female => 1 Male => 2 |
字符串枚举:枚举成员的值是字符串
1 | enum Gender { Female = '女', Male = '男' } |
注意:字符串枚举没有自增长的行为,因此,每个成员必须有初始值
1 | console.log(Gender.Female) //女 |
两种常用的枚举总结:
数字枚举:枚举成员的值为数字,默认情况下就是数字枚举
1
2enum Gender { Female, Male }
enum Gender { Female = 100, Male } //初始化成员的值特点:成员的值是从0开始自增的数值
字符串枚举:枚举成员的值为字符串
1
enum Gender { Female = '女', Male = '男' }
特点:没有自增行为,需要为每一个成员赋值!
枚举是一组有名字的常量(只读)的集合。