什么是typescript ?
ts是具有类型语法的 js , 是一门强类型的变成语言,是微软开发的一款开源编程语言, 是由 Type + JavaScript 组合而成,type是类型 => 就是在js的基础上,为js添加了类型的支持,简称:TS。
ts带来了什么好处?
1、静态类型检查,提前发现代码错误,因为在书写 ts 代码的时候会编写类型,必须严格按照编写的类型进行编译,这样就可以在代码还没运行前,在静态类型发现错误的存在。
2、良好的代码提示,提高了开发效率,也是在 Type 的基础上面,定义了类型之后,再访问变量时变量命会直接提示出来,若是写错了,会直接报错。
(TS 适合开发中大型项目,对于小项目会变得很繁琐)
怎么使用 TS ?
1、安装编译 TS 的工具包
a. 全局安装 typescript 包(编译引擎)-> 注册 tsc
命令 npm install -g typescript
b. 新增 hello.ts 文件, 执行 tsc hello.ts 命令生成hello.js文件
c. 执行 node hello.js 运行js文件查看效果
2、搭建自动编译环境
基于工程化的TS开发模式(webpack / vite),TS的编译环境已经内置了,无需手动安装配置,通过以下命令即可创建一个最基础的自动化的TS编译环境。
npm create vite@latest ts-pro – --template vanilla-ts
命令说明:
- npm create vite@latest 使用最新版本的vite创建项目
- ts-pro 项目名称
- – --template vanilla-ts 创建项目使用的模板为原生ts模板
什么是类型注解?
**概念:**类型注解指的是给变量添加类型约束,它的好处是:
- 使变量只能被赋值为约定好的类型
- 编写代码的过程中可以有相关的类型提示
示例代码:
let age: number = 18
说明:代码中的 : number 就是类型注解
作用:为变量添加类型约束。比如,上述代码中,约定变量 age 的类型为 number 类型
解释:约定了什么类型,就只能给变量赋值该类型的值,否则,就会报错
约定了类型之后,代码的提示就会非常的清晰
TS支持的常用类型注解
● JS 已有类型
○ 原始类型,简单类型(number/string/boolean/null/undefined)
○ 复杂数据类型(数组,对象,函数等)
● TS 新增类型
○ 联合类型
○ 自定义类型(类型别名)
○ 接口
○ 元组
○ 字面量类型
○ 枚举
○ void
○ … …
简单类型如何进行类型注解
简单类型的注解完全按照 JS的类型(全小写的格式)来书写即可
let age: number = 18
let name: string = '张三'
let isShow: boolean = false
let nullValue: null = null
let undefineValue: undefined = undefined
什么是类型推论?
说到这个问题就要问一句了,是不是每个简单的变量都要写类型注解?
let age: number = 18
let myName: string = '小花'
let isLoading: boolean = false
就比如上述代码,这种代码再写类型注解,是不是有点多余了。
这个时候就要说到类型推论这个东西了
类型推论就是某些没有明确指出类型的地方,TS 的类型推论机制会帮助提供类型
换句话说:由于类型推论的存在,有些场合下的类型注解可以省略不写
发生类型推论的 2 种常见场景:
- 声明变量并初始化时
- 决定函数返回值时
示例代码:
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number) {
return num1 + num2
}
技巧
- 能省略类型注解的地方就省略(偷懒,充分利用TS类型推论的能力,提升开发效率)
- 如果不知道类型,可以通过鼠标放在变量名称上,利用 VSCode 的提示来查看类型
怎么实现数组类型注解呢?
说完基本数据类型的类型注解,下面就来说一下数组的类型注解,说这个之前要先问一下注解数组有什么用呢?
注解数组有什么用?
变量被注解为数组类型之后,有两点好处:
- 不仅可以限制变量类型为数组而且可以限制数组成员的类型
- 编码时不仅可以提示数组的属性和方法而且可以提示成员的属性和方法
如何注解数组类型?
使用数据类型对变量进行类型注解有两种语法
语法1:
let arr: numbner[] = [1, 2, 3]
上面的代码表示: 变量arr只能用来保存数组类型,并且数组的元素必须是number类型
语法2:泛型函数
let arr: Array<number> = [1, 2, 3]
联合类型
需求
数组中既有 number 类型,又有 string 类型,这个数组的类型应该如何写?
let arr: (number | string)[] = [1, 'a', 3, 'b']
联合类型
概念:将多个类型合并为一个类型对变量进行注解
解释:|(竖线)在 TS 中叫做联合类型,即:由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种
注意:这是 TS 中联合类型的语法,只有一根竖线,不要与 JS 中的或(|| 或)混淆了
类型别名-type
为什么需要类型别名呢,类型别名有什么用处呢?带着这些问题往下面看!
思考
const arr1:(number | string)[] = [1, '1']
const arr2:(number | string)[] = ['a', 'b']
如上代码中,存在类型注解重复的问题: (number | string)[] 这个类型出现了多次, 怎么优化呢?这就要说类型别名了。
类型别名
定义: type 别名 = 类型
别名可以是任意的合法字符串,一般首字母大写
例子: type MyArr = (number | string) []
作用:给类型起别名 —> 定义了新类型
使用:
type MyArr = (number | string) []
const arr1:MyArr = [1, '1']
const arr2:MyArr = ['a', 'b']
所谓类型别名就是将两个变量相同的类型整合起来,直接调用即可。
函数类型
介绍过数组类型之后,下面来说一下函数类型。
1. 基础使用
概念:函数类型是指给函数添加类型注解,本质上就是给函数的参数和返回值添加类型约束
说明:
a. 函数参数注解类型之后不但限制了参数的类型还限制了参数为必填
b. 函数返回值注解类型之后限制了该函数内部return出去的值必须满足类型要求
好处:
a. 避免因为参数不对导致的函数内部逻辑错误
b. 对函数起到说明的作用
2. 函数表达式
函数表达式的类型注解有两种方式:
a. 参数和返回值分开注解
b. 函数整体注解
参数和返回值分开注解
函数整体注解(只针对于函数表达式)
函数可选参数
概念:可选参数表示当前参数可传可不传,一旦传递实参必须保证参数类型正确
**说明:**lastName参数表示可选参数,可传可不传,一旦传递实参必须保证类型为string类型
函数无返回值 - void
概念:JS中的有些函数只有功能没有返回值,此时使用void进行返回值注解,明确表示函数没有函数值
注意事项:
- 在JS中如果没有返回值,默认返回的是undefined
- 在TS中 void和undefined不是一回事:
a. undefined在TS中是一种明确的简单类型,如果指定返回值为undefined,那返回值必须是undefined类型
b. void表示没有返回值
interface-接口-基本使用
作用
作用: 用interface来描述对象数据的类型(常用于给对象的属性和方法添加类型约束)
**说明:**一旦注解接口类型之后对象的属性和方法类型都需要满足要求,属性不能多也不能少
典型场景
场景:在常规业务开发中比较典型的就是前后端数据通信的场景
- 前端向后端发送数据:收集表单对象数据时的类型校验
2. 前端使用后端数据:渲染后端对象数组列表时的智能提示
interface接口的可选设置和继承
场景
对象的某个属性是可选的。
**例如:**从后端取回的商品数据中,一定有id,name, price,但是imgUrl是可选的。表示有些商品没有配图片。
const goodList = [
{id:1, name: '手机', price: 2999, imgUrl: 'http://w.g1.png'},
{id:1, name: '毛巾', price: 9}
]
我们这么约定goodList的格式,下面的代码会报错:
interface goodItem {
id: number;
name: string;
price: number;
imgUrl: string;
}
const goodList: goodItem[] = [
{id:1, name: '手机', price: 2999, imgUrl: 'http://w.g1.png'},
{id:1, name: '毛巾', price: 9} // 这里会报错
]
可选设置
概念: 通过 ?对属性进行可选标注,赋值的时候该属性可以缺失,如果有值必须保证类型满足要求。
格式:
interface 接口名{
属性1:类型1,
属性2?:类型2, // 属性2是可选的
属性3?:类型3, // 属性3是可选的
}
代码
interface goodItem {
id: number;
name: string;
price: number;
imgUrl?: string; // 可选的
}
const goodList: goodItem[] = [
{id:1, name: '手机', price: 2999, imgUrl: 'http://w.g1.png'},
{id:1, name: '毛巾', price: 9} // 这里也是正确的
]
接口的继承
概念:接口的很多属性是可以进行类型复用的,使用 extends 实现接口继承,实现类型复用。
// 正常的商品
interface goodItem {
id: number;
name: string;
price: number;
imgUrl?: string;
}
// 打折的商品:正常商品 + newPrice + effectDate
interface goodItemDiscount {
id: number;
name: string;
price: number;
imgUrl?: string;
newPrice: number;
effectDate: Date
}
继承之后
interface goodItemDiscount extends goodItem {
newPrice: number;
effectDate: Date
}
type注解对象类型
注解对象
概念:在TS中对于对象数据的类型注解,除了使用interface之外还可以使用类型别名来进行注解,作用相似
type + 交叉类型模拟继承
类型别名配合交叉类型(&)可以模拟继承,同样可以实现类型复用
interface 对比 type
相同点
-
都能描述对象类型
-
都能实现继承,interface使用extends, type配合交叉类型
不同点 -
type除了能描述对象还可以用来自定义其他类型
-
同名的interface会合并(属性取并集,不能出现类型冲突)
-
同名type会报错
在注解对象类型的场景下非常相似,推荐大家使用type, type更加灵活
(更多关于 TS 的见解也可以评论区留言,喜欢的可以点个小心心,收藏一下 感谢支持)