TypeScript
从编程语言的动静来区分,TypeScript 属于静态类型的编程语言,JS 属于动态类型的编程语言。
静态类型:编译期做类型检查;
动态类型:执行期做类型检查。
代码编译和代码执行的顺序:1 编译 2 执行。
TypeScript 初始化
1 安装编译 TS 的工具包
问题:为什么要安装编译 TS 的工具包?
回答:Node.js/浏览器,只认识 JS 代码,不认识 TS 代码。需要先将 TS 代码转化为 JS 代码,然后才能运行。
安装命令:npm i -g typescript。
typescript 包:用来编译 TS 代码的包,提供了 tsc 命令,实现了 TS -> JS 的转化。 验证是否安装成功:tsc –v(查看 typescript 的版本)。
2 编译并运行 TS 代码
1. 创建 hello.ts 文件(注意:TS 文件的后缀名为 .ts)。
2. 将 TS 编译为 JS:在终端中输入命令,tsc hello.ts(此时,在同级目录中会出现一个同名的 JS 文件)。
3. 执行 JS 代码:在终端中输入命令,node hello.js。
3 简化运行 TS 的步骤
问题描述:每次修改代码后,都要重复执行两个命令,才能运行 TS 代码,太繁琐。 简化方式:使用 ts-node 包,直接在 Node.js 中执行 TS 代码。
安装命令:npm i -g ts-node(ts-node 包提供了 ts-node 命令)。
使用方式:ts-node hello.ts。
解释:ts-node 命令在内部偷偷的将 TS -> JS,然后,再运行 JS 代码。
TypeScript 常用类型
1. JS 已有类型 l 原始类型:number/string/boolean/null/undefined/symbol。 l 对象类型:object(包括,数组、对象、函数等对象)。
2. TS 新增类型 l 联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any 等。。
1 类型注解
let age:number =18
说明:代码中的 : number 就是类型注解。
作用:为变量添加类型约束。约定变量 age 的类型为 number(数值类型)。
解释:约定了什么类型,就只能给变量赋值该类型的值,否则,就会报错。
2 原始类型
原始类型:number/string/boolean/null/undefined/symbol。
特点:简单。这些类型,完全按照 JS 中类型的名称来书写。
let sum:number=18
let myName:string='刘老师'
let isLoading:boolean=false
let L:null=null
let b:undefined=undefined
let c:symbol=Symbol()
3 数组类型
数组类型的两种写法:(推荐使用 number[] 写法)
let nums:number[]=[1,2,3]
let nums2:Array<number>=[1,2,3]
let b:boolean[]=[true]
联合类型:由两个或多个其他类型组成的类型、表示可以是这些类型中的任意一种
let arr:(number|string)[]=[1,2,'2','44']
//不添加小括号、表示arr2既可以是number类型、又可以是string类型
// let arr2:number|string[]=['2','44']
// let arr2:number|string[]=2
3 类型别名
类型别名(自定义类型):为任意类型起别名。
使用场景:当同一类型(复杂)被多次使用时,可以通过类型别名,简化该类型的使用。
type CustomArray =(number|string)[]
let arrL:CustomArray=[1,2,'2','44']
let arrs:CustomArray=[1,'2',22,'33']
解释:
1. 使用 type 关键字来创建类型别名。
2. 类型别名(此处的 CustomArray),可以是任意合法的变量名称。
3. 创建类型别名后,直接使用该类型别名作为变量的类型注解即可。
4 函数类型
指的是函数参数和返回值的类型
指定类型的方式
1. 单独指定参数、返回值的类型
2. 同时指定参数、返回值的类型
1. 单独指定参数、返回值的类型:
function add(num1:number,nums2:number):number{
return num1+nums2
}
const add1=(num1:number,nums2:number):number=>num1+nums2
console.log(add1(1,2))
2. 同时指定参数、返回值的类型:
// 同时指定参数、返回值的类型:
(num1:number,num2:number)=>number指定参数类型、返回值类型
const addLhs:(num1:number,num2:number)=>number=(num1,num2)=>num1+num2
console.log(addLhs(1,4))
解释:当函数作为表达式时,可以通过类似箭头函数形式的语法来为函数添加类型。
注意:这种形式只适用于函数表达式。
3. 如果函数没有返回值、那么函数的返回值类型为:void
### 使用:void类型表示当前函数没有返回值
function greeet(name:string):void{
console.log('你好ts',name)
//return '22' 指定了void在写return会报错
}
greeet('李寒松')
4. 函数可选参数
使用函数实现某个功能时,参数可以传也可以不传。这种情况下,在给函数参数指定类型时,就用到可选参数了。
比如,数组的 slice 方法,可以 slice() 也可以 slice(1) 还可以 slice(1, 3)。
function mySlice(start?:number,end?:number):void{
console.log('开始索引',start,'结束索引',end);
}
mySlice(1,20)
mySlice(1)
mySlice()
可选参数:在可传可不传的参数名称后面添加 ?(问号)。
注意:可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数。
5 对象类型
ts中的对象类型就是在描述对象的结构(有什么属性与方法)
//根据指定好的类型为对象赋值
let person:{ name:string;age:number; //在一行中定义类型、加分号分隔
sayHi():void//独占一行可以不要分号
greet:(name:string)=>void //类型也可箭头函数
}={
name:'李寒松',
age:20,
sayHi(){},
greet:(name)=>console.log(name)
}
person.greet('22')
展示形式
属性名: 类型
方法名(): 返回值类型
注:在一行中定义类型、加分号分隔
独占一行可以不要分号
类型也可箭头函数
可选属性:在可传可不传的参数名称后面添加 ?(问号)。(与可选参数语法一致)
const myAxios=(config:{url:string;method?:string}):void=>{
console.log('333')
}
myAxios({url:''})
6 接口 interface
当一个对象类型被多次使用、可以使用interface来描述对象的类型、达到复用性
使用interface关键字声明接口、接口名字作为对象类型使用
interface只能为对象指定类型
interface IPerson {
name: string
age: number
sayHi: () => void
}
let person: IPerson = {
name: '李XX',
age: 18,
sayHi: () => { }
}
let personLIU: IPerson = {
name: '溜XX',
age: 222,
sayHi: () => {}
}
7 接口继承 extends
接口继承:把公共的方法或属性抽离出来、通过继承实现复用
extends关键字实现继承
interface Point2D {
x: number
y: number
}
interface Point3D extends Point2D {
z: number
}
let p3: Point3D = {
x: 1,
y: 0,
z: 0
}
8 元组(Tuple)
元组类型:标记出有多少个元素,以及每个元素的类型
//这种方式数字中可以出现任意多个数字
let postition:number[]=[39.5427,116.2317]
//指定元素个数、及类型
let postition1:[number,number]=[12.2222,114.2316]
9 类型推论
推荐:能省略类型注解的地方就省略
//声明变量并立即初始化值、此时、可以省略类型注解
let agelhs=18
//根据返回值、推论了返回值类型
function add(num1:number,num2:number){
return num1+num2
}
10 类型断言
使用类型断言(as关键字)来指定一个明确的类型
//形式一
const aLink=document.getElementById('link') as HTMLAnchorElement
//形式2(不常用)
const aLink2=<HTMLAnchorElement>document.getElementById('link')
aLink.href
aLink2.href
技巧:通过console.dre()打印dom元素为对象、查看其中的类型
11 字面量类型
1. 概述
let str1='Hello Ts'
const str2='Hello Ts'
// 通过 TS 类型推论机制,可以得到答案:
// 1. 变量 str1 的类型为:string。
// 2. 变量 str2 的类型为:'Hello TS'。
// 解释:
// 1. str1 是一个变量(let),它的值可以是任意字符串,所以类型为:string。
// 2. str2 是一个常量(const),它的值不能变化只能是 'Hello TS',所以,它的类型为:'Hello TS'。
const str3:'Hello Ts'='Hello Ts'
let ages:18=18
// 注意:此处的 'Hello TS',就是一个字面量类型。也就是说某个特定的字符串也可以作为 TS 中的类型。
//其他任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用。
2. 使用场景
使用模式:字面量类型匹配联合类型一起使用
使用场景:用来表示一组明确的可选值列表
function changeDirection(direction:'up'|'down'|'left'|'right'){
console.log(direction)
}
//指定direction的值只能是'up'|'down'|'left'|'right'其中一下
changeDirection('down')
比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个。
解释:参数 direction 的值只能是 up/down/left/right 中的任意一个。
优势:相比于 string 类型,使用字面量类型更加精确、严谨。
12 枚举类型
enum定义枚举类型
enum Direction{
up, Down, Left, Right
}
//使用枚举定义类型注解
function changeDirection(Direction:Direction){
console.log(Direction)
}
//当函数的参数类型是枚举时、 调用函数传入的参数就必须是这个枚举中的任意一个
changeDirection(Direction.Left)
(数字枚举)
enum Direction{
数字枚举:枚举成员是有值的,默认为:从 0 开始自增的数值。
up, Down, Left, Right
}
给枚举中的成员初始化值。
enum Direction{
//初始化枚举、
up=2, Down=4, Left=6, Right=8
}
##### (字符串枚举)
字符串枚举:枚举成员中的值是字符串
注:每个成员中的值必须初始化
enum Direction{
//初始化枚举
up='lhs1', Down='lhs2', Left='lhs2', Right='lhs3'
}
枚举特性:枚举不仅用作类型、还提供值、枚举类型还会被编译为js代码
13 any类型
注意:不推荐使用any,使用any会使该属性失去类型保护机制
let obj:any={ x:0}
//访问不存在的属性
console.log(obj.aaa)
//当成函数调用
obj()
//赋值给其他类型的变量
let n:number=obj
以上操作都不在提示错误
隐式any类型
//以下具有隐式any类型
1. 声明变量不定义类型、不赋值
let ss
ss=''
2. 函数参数不定义类型
function add(num1,num2){
}
14 typeof
typeof:查询变量或对象属性的类型
使用场景:根据已有变量值、获取该值的类型、来简化书写
let p={ x:1,y:2}
//在类型上下文(类型注解的地方)中获取P对象中属性的类型
function formatPoint(point: typeof p){}
//function formatPoint(point: {x:number;y:number} p){}//与typeof方式一致
formatPoint({x:2, y:4})
let num:typeof p.x //获取属性中的类型
function add(num1:number,num2:number){
return num1+num2
}
let ret:typeof add(1,2) //typeof不能查询函数调用形式的类型