介绍
TypeScript 是具有类型语法的 JavaScript,是一门强类型的编程语言
它会将代码编译为js,运行js文件
优点
- 能在编写的时候提前发现代码错误
- 有代码提示
使用场景
一般小型开发不用ts比较占用性能
- 大型的应用
- 团队协作开发
- 在编写通用的代码库
编译环境
ts编写的代码无法直接运行在js引擎(浏览器/Nodejs)中运行的,需要经过编译成js代码
搭建手动编译环境
- 安装typescript包(编译引擎
- 注册tsc命令 npm install typescript
若安装在局部环境,需要在命令前加npx
- 新增测试文件,执行 tsc 文件名.ts 命令生成hello.js文件
- 执行node 文件名.js 文件查看内容
- 注册tsc命令 npm install typescript
var message = 'hello,world';
console.log(message);
搭建工程化下的自动编译环境
手动编译环境需要使用命令行,可以看见编译后的js文件 自动编译环境不会再生成js文件,由环境辅助编译环境完成ts文件的执行
使用vite搭建
使用命令
npm create vite@latest ts-pro -- --template vanilla-ts
- npm create vite@latest 使用最新版本的vite创建项目
- ts-pro 项目名称
- -- --template vanilla-ts 创建项目使用的模板为原生ts模板
执行图中的命令行
通过vscode打开
使用npm安装
创建根目录
- 安装typescript包
npm install typescript
安装后会生成这些文件
- 初始化配置文件
npm tsc --init
创建tsconfig.json 文件
- 修改
tsconfig.json中的配置项- "rootDir": "./src", // 根目录
- "outDir": "./dist", // 出口文件
- 创建目录
src和dist
- 执行代码查看效果
npx tsc -w
TS类型注释
若没有设置类型约束,ts会根据第一次初始化的值对变量进行类型约束
- JS已有类型
- 简单类型
- number
- string
- boolean
- null
- undefined
- 复杂类型
- 数组
- 函数
- 简单类型
- TS新增类型
- 联合类型
- 类型别名
- 接口(interface)
- 字面量类型
- 泛型
- 枚举
- void
- any
简单数据类型注释
let age: number = 18 // number类型注解
let uname: string = 'zhangsan' // string类型注解
let isWorking: boolean = true // 布尔值类型注解
let nullValue: null = null // null类型注解
let undefinedValue: undefined // undefined类型注解
console.log(age, uname, isWorking, nullValue, undefinedValue)
undefined和null是特殊值
在ts.config.json中有"strictNullCheck"属性若改为false则可以进行空值传递(不检查空值)
数组类型注解
数组类型注解可以限制变量类型为数组,也可以限制数组成员的类型
编码的时候能提供数组和成员的属性和方法
两种数组类型注解方式:
- 类型[]
let arr1: number[] = [1, 2, 3]
- Array
<number>
let arr2: Array<number> = [1, 2, 3]
函数类型注解
函数类型注解可以给传递的参数以及函数的返回值添加注解
基础类型
// 两数相加函数
function add(a: number, b: number): number {
return a + b
}
add(1, 2)
let res: number = add(1, 2)
console.log(res)
函数表达式(箭头函数)
函数表达式有两种函数类型注解
- 分开注解
// 两数相加函数
const res = (a: number, b: number): number => {
return a + b
}
console.log(res(1, 2))
- 整体注解(库文件)
// 两数相加函数
type AddFn = (a: number, b: number) => number
const res: AddFn = (a, b) => {
return a + b
}
console.log(res(3, 2))
整体注解是通过类型别名来进行注解
// 两数相加函数
type AddFn = (a: number, b: number) => number
const res: AddFn = (a, b) => {
return a + b
}
console.log(res(3, 2))
可选参数
在函数的形参中可以添加?表示当前的形参可传可不传。如果传值则保证参数类型正确
参数的后面可以直接赋值作为形参的默认值
ts中默认值和可选参数不能同时出现
// 可选参数(必须在所有参数的末尾)
function introduceMyself(name: string, age?: number): string {
if(age) {
return name + '今年' + age + '岁'
}
return name
}
console.log(introduceMyself('geniusXiang'))
console.log(introduceMyself('geniusXiang', 18))
无返回值 - void
在函数返回值的类型约束中添加void表示函数没有返回值
在JS中没有返回值,默认返回的是
undefined.TS中undefined是一种明确的简单类型。如果返回值为undefined,则返回值必须是undefined
let arr: Array<number> = [1, 2, 3]
function eachArr(arr: number[]): void {
arr.forEach(item => {
console.log(item)
})
}
eachArr(arr)
联合类型注解
可以将一个变量进行多个类型注解
let num: number | string
num = '123'
num可以是数字类型也可以是字符串类型
let num: number | string[]
num = ['123']
num可以是数字类型也可以是字符串数组类型
let num: (number | string)[]
num = [1, 2, 3, '4']
num可以是数字的数组也可以是字符串数组,也可以混合
类型别名
通过type关键词给类型起别名以达到方便复用的目的
一般类型别名使用大驼峰命名方式
type ItemType = number | string
let a: ItemType
a = '123'
type注解对象
在TS中对于对象的类型注释,除了使用interface还可以使用类型别名进行注释
type StayAtSchool = {
studingDurationMinutes: number
isDrinking?: boolean
}
let student1: StayAtSchool = {
studingDurationMinutes: 30,
}
student1 = {
studingDurationMinutes: 10,
isDrinking: false
}
type + 交叉类型模拟继承
类型别名配合交叉类型&实现类型服用
// type 模拟继承(交叉类型&)
// 原价商品
type GoodsType = {
id: string
price: number
}
// 打折类型商品
type DiscountGoodsType = GoodsType & {
discount: number
}
let goods: DiscountGoodsType = {
id: '百事可乐',
price: 2.7,
discount: 0.9
}
console.log(goods)
并集
// 并集
type GoodsType = {
id: string
price: number
}
type DisGoodsType = {
price: number
discount: number
}
let goods: GoodsType & DisGoodsType = {
id: '可乐',
price: 0.7,
discount: 0.9
}
interface接口数据类型
一般接口数据类型使用大驼峰方式命名
interface常用于给对象添加类型约束,属性不可多不可少
interface Person {
name: string
age: number
isWorking: boolean
}
const aa: Person = {
name: 'geniusXiang',
age: 18,
isWorking: true
}
接口类型使用场景
- 表单对象类型校验
interface LoginForm {
username: string
password: string
isCheckingAgreement: boolean
}
const userOne: LoginForm = {
username: 'geniusXiang',
password: '123456',
isCheckingAgreement: true
}
- 渲染后端列表场景
// 渲染后端列表场景说明
interface Data {
message: string
}
interface ResponseData {
code: number
data: Data
}
let dataSuccess = {
code: 200,
data: {
message: '请求通过'
}
}
let dataReject = {
code: 500,
data: {
message: '你访问的页面丢失'
}
}
接口的可选设置
通过可选符?对属性进行标记,该属性可有可无,若是有则要保证类型满足约束
interface StayAtSchool {
studingDurationMinutes: number
isDrinking?: boolean
}
let student1: StayAtSchool = {
studingDurationMinutes: 30,
}
student1 = {
studingDurationMinutes: 10,
isDrinking: false
}
interfance的继承
接口的属性可以使用extends实现接口的继承
// 原价商品
interface GoodsType {
id: string
price: number
}
// 打折类型商品
interface DiscountGoodsType extends GoodsType {
discount: number
}
let goods: DiscountGoodsType = {
id: '百事可乐',
price: 3,
discount: 0.9
}
interface 对比 type
- 相同点
- 都能描述对象类型
- 都能实现继承,interface使用extends,type配合交叉类型
- 不同点
- type除了能描述对象还可以用来自定义其他类型
- 同名的interface会合并(属性取并集,不能出现类型冲突),同名的type会报错
字面量类型
使用 js字面量 作为类型对变量进行约束.字面量类型比普通的类型更加精确
// 普通的number类型 可以赋值任何数值
let count: number
count = 100
count = 200
// 字面量类型100 只能赋值为100
let count1: 100
count1 = 100
实际应用
type Gender = '男' | '女'
let gender:Gender = '男'
gender = '女'
例如
element-ui中的button属性
type Props = {
type: 'primary' | 'success' | 'danger' | 'warning'
}
字面量类型与const
let str1 = 'this is str' // str1 是string类型
const str2 = 'this is const string' // str2是字面量类型
const声明常量称之为常量,常量不能进行重新赋值
any 任意类型
// any
let a: any = 'hello, world'
a = true
a = 100
a = null
a = undefined
a = []
a = () => {}
a = {}
// 使用场景
function fn1(...rest: any[]) {}
unknown 未知类型
标记为unknown类型的可以赋值给其他类型
// unknown
let u: unknown
u = 100
u = null
u = undefined
u = []
// ......
unknown和any
- 相同点:都可以接收其他数据类型
- 不同点:unknown类型的数据无法赋值给其他类型的数据
never
never一般使用较少,表示永不存在的值,常用于标注一个函数抛出错误时的返回值
// never
let fn1 = (): never => {
throw new Error('出错啦')
}
tuple 元组
元组的概念只存在于ts中
- 长度固定
- 每个位置上的元素类型固定
// 数组
let list1: (string | number)[] = [1, 2, 3, 'a', 'b', 'c']
// 元组
let list2: [string, number] = ['abc', 100]
枚举类型
// 枚举类型
enum Male {
man = '男',
woman = '女'
}
console.log(Male.man)
enum list {
s1,
s2,
s3
}
console.log(list.s1, list.s2, list.s3)
类型断言
- 类型推断:在不进行标注的情况下,ts根据赋值进行自动的标注
- 类型断言:手动的进行判断(少用,类型断言容易导致判断失误)
// const app = document.querySelector('#app') as HTMLDivElement
// const content = app.innerHTML
// console.log(content)
// const app = document.querySelector('#app')! //非空断言
// const content = app.innerHTML
// console.log(content)
// const app = document.querySelector('#app')
// const content = app?.innerHTML // 可选判断
// console.log(content)
const app = document.querySelector('#app')
if(app) {
const content = app.innerHTML
console.log(content)
}
泛型
通过泛型,可以动态的设置类型参数。比如定义一个函数的时候,参数的类型并不确定,那么可以让用户在调用函数的时候传入具体参数类型即可
// 泛型
function fn1<T>(param: T) {
console.log(param)
}
fn1<number>(123)
// 定义对象的时候使用泛型
type objType<T> = {
user: string,
info: T
}
泛型通过extends实现继承
const obj: objType<string> = {
user: 'zs',
info: 'eating'
}
// 可以通过extends实现继承
function getLength<T extends string>(args: T) {
return args.length
}
// getLength('hello,world')
泛型继承自定义对象
// 继承自定义对象
type obj = {
length: number,
}
function getLength<T extends obj>(arg: T):number {
return arg.length;
}