文章目录
TypeScript 介绍
TypeScript 是一种带有 类型语法 的 JavaScript 语言,在任何使用 JavaScript 的开发场景中都可以使用。
TypeScript 作用
TS 优势:
○ 更早发现错误,提高开发效率
○ 随时随地提示,增强开发体验
○ 强大类型系统,代码可维护性更好,重构代码更容易
○ 类型推断机制,减少不必要类型注解,让编码更简单
○ 最后:Vue3源码TS重写,React和TS完美配合,Angular默认支持TS,大中型前端项目首选。
TypeScript 编译
全局安装:
# npm 安装
npm i -g typescript
# yarn 安装
yarn global add typescript
# 部分mac电脑安装需要sudo权限
# sudo npm i -g typescript
# sudo yarn global add typescript
查看版本:
tsc -v
将ts文件转为js文件:tsc xxx.ts
在开发中:一般使用 webpack、vite 等工具自动构建编译。
TS 常用类型:
JS 已有类型
简单类型:number string boolean null undefined
复杂类型:对象 数组 函数
TS 新增类型
联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any、泛型 等
原始类型
使用简单,完全按照 JS 的类型来书写即可
let age: number = 18;
let myName: string = '黑马程序员';
let isLoading: boolean = false;
let nullValue: null = null;
let undefinedValue: undefined = undefined;
数组类型
//写法1
let numbers: number[] = [1, 3, 5] //推荐
//写法2
let numbers2: Array<string> = ['a', 'b', 'c']
联合类型 将多个类型合并为一个类型
let list: (string | number)[] = [1, 2, 3, 'abc'] //数组里面是数字或者字符串
let arr: number | string[]; //可能是我数字,也可能是数组里面包字符串
类型别名
○ type 类型别名 = 具体类型 基本语法
○ 定义类型别名,遵循大驼峰命名规范,类似于变量
○ 使用类型别名,与类型注解的写法一样即可
// let arr: ( number | string )[] = [ 1, 'a', 4]
// 类型别名: type 类型别名 = 具体类型
type CustomArr = (number | string)[];
let arr: CustomArr = [1, 'a', 4];
函数类型
-
给函数指定类型,其实是给 参数 和 返回值 指定类型。
-
两种写法:
-
在函数基础上 分别指定 参数和返回值类型
// 函数声明 function add(num1: number, num2: number): number { return num1 + num2; } // 箭头函数 const add1 = (num1: number, num2: number): number => { return num1 + num2; };
-
使用类型别名 同时指定 参数和返回值类型
type AddFn = (num1: number, num2: number) => number; const add: AddFn = (num1, num2) => { return num1 + num2; };
-
interface vs type
i. 它们都可以定义对象类型
ii. 它们都可以复用,interface 使用 extends , type 使用 &
iii. type 不能重复定义,interface 可以重复会合并
iv. interface可以给接口扩展:比如给vue-router的meta,它的类型是RouteMeta,但里面没有写值,所以可以用interface在types文件夹里给meta扩展
泛型
作用:泛型可以提高复用;支持未来出现的类型
在type上的应用
// type UserResponse = {
// msg: string
// code: number
// data: {
// name: string
// age: number
// }
// }
// type GoodsResponse = {
// msg: string
// code: number
// data: {
// id: number
// goodsName: string
// }
// }
type Date<Type> = { // Type传入的参数
msg: string
code: number
data: Type
}
type User = {
name: string
age: number
}
type Goods = {
name: string
age: number
}
type UserResponse = Date<User>
type GoodsResponse = Date<Goods>
在interface上的应用
// 对象:{ id(){}, ids(){} } 获取一个id 获取所有id
// 如果获取id,不管是一个还是所有,类型都是一样的
interface IdFnObj<T> {
id(): T
ids(): T[]
}
let obj: IdFnObj<number> = { // number是下面返回的数据类型
id() {
return 2
},
ids() {
return [1, 2, 3]
}
}
在函数上的应用
// 需求:传参的类型是什么,返回的类型就是什么
// const getId = (id: number): number => {
// return id
// }
// function getId<T>(id: T): T {
const getId = <T>(id: T): T => { // 第一个T是函数的泛型,写在参数前面,作用是传递泛型T,供后面使用
return id
}
let id1 = getId<number>(2) // 这里的number指的是后面参数的类型,值会给到上面函数中的第一个T
let id2 = getId('2') // TS的类型推倒,参数的类型,作为泛型的类型传递给函数
let id3 = getId<{ name: string; age?: number }>({ name: 'jack' }) // age?: number | undefined
案例 - 使用 TS 实现访问历史记录功能
// 格式化时间的函数
// 1、参数是Date类型
// 2、参数是string类型
// 3、如果不传参,默认使用当前时间
const formatTime = (date?: Date | string): string => {
if (!date) date = new Date()
if (typeof date === 'string') date = new Date(date) // 需要判断是否string类型,是的话要转,不然string没有下面的方法
const h = date.getHours()
const m = date.getMinutes()
const s = date.getSeconds()
return `${h}:${m}:${s}`
}
// const time1 = formatTime(new Date('2022-10-10 18:10:17')) // 里面的new Date是一个Date类型
// console.log(time1)
// const time2 = formatTime('2022-10-10 18:10:47')
// console.log(time2)
// const time3 = formatTime()
// console.log(time3)
// 声明程序需要的类型,每一项是一个对象,整体是一个数组,需要一个不变的key
type Item = {
count: number
time: string
}
type List = Array<Item>
const key = 'ts-demo'
// 封装一个获取本地存储的数组函数
const getData = () => {
const str = localStorage.getItem(key) || '[]'
const list = JSON.parse(str) as List // ts默认把list类型判断为any,所以设置类型断言
return list
}
// 记录访问历史的函数
const updateData = () => {
const list = getData() // 获取原数据
const lastItem = list[list.length - 1]
list.push({
count: lastItem ? lastItem.count + 1 : 1, // 如果数组list中没有数据,则默认为1,否则最后一个 count+1
time: formatTime(),
})
localStorage.setItem(key, JSON.stringify(list)) // 改完后存本地
}
// 封装渲染函数
const render = () => {
updateData()
const list = getData()
const app = document.querySelector('#app') as HTMLDivElement
app.innerHTML = list.map(item => `次数${item.count} 时间${item.time}`).join('<br/>')
}
render()