TypeScript

背景:

JS 的类型系统存在“先天缺陷”弱类型,JS 代码中绝大部分错误都是类型错误(Uncaught TypeError) 开发的时候,定义的变量本应该就有类型 这些经常出现的错误,导致了在使用 JS 进行项目开发时,增加了找 Bug、改 Bug 的时间,严重影 响开发效率 。

从编程语言的动静来区分,TypeScript 属于静态类型的编程语言JavaScript 属于动态类型的编程 语言

  • 静态类型:编译期做类型检查
  • 动态类型:执行期做类型检查

对于 TS 来说:在代码编译的时候(代码执行前)就可以发现错误(早)

Vue 3 源码使用 TS 重写、Angular 默认支持 TS、React 与 TS 完美配合,TypeScript 已成为大中型前端 项 目的首选编程语言

目前,前端最新的开发技术栈:

  1. React: TS + Hooks
  2. Vue: TS + Vue3
    注意: Vue2 对 TS 的支持不好~

安装编译 TS 的工具包

目标:能够安装ts的工具包来编译ts

内容: 问题:为什么要安装编译 TS 的工具包?

回答:Node.js/浏览器,只认识 JS 代码,不认识 TS 代码。

需要先将 TS 代码转化为 JS 代码,然后 才能运行 安装命令:

npm i -g typescript 或者 yarn global add typescript typescript

用来编译 TS 代码的包,提供了 tsc 命令,实现了 TS -> JS 的转化

注意:Mac 电脑安装全局包时,需要添加 sudo 获取权限: sudo npm i -g typescript yarn

全局安装:

sudo yarn global add typescript

验证是否安装成功:tsc –v(查看 typescript 的版本)

创建基于TS的vue项目

目标:能够使用vite创建vue-ts模板的项目

内容: 基于vite创建一个vue项目,使用typescript模板

yarn create vite vite-ts-demo --template vue-ts

TypeScript基础

TypeScript 是 JS 的超集,TS 提供了 JS 的所有功能,并且额外的增加了:类型系统

所有的 JS 代码都是 TS 代码

JS 有类型(比如,number/string 等),但是 JS 不会检查变量的类型是否发生变化,而 TS 会 检查 TypeScript 类型系统的主要优势:可以显示标记出代码中的意外行为,从而降低了发生错误的可能 性

 let age = 18
 let age: number = 18  
  • : number 就是类型注解
  • 为变量添加类型约束。比如,上述代码中,约定变量 age 的类型为 number 类型
  • 约定了类型之后,代码的提示就会非常的清晰
  • 变量的初始值的类型 就是该变量的类型
// 错误代码:
// 错误原因:将 string 类型的值赋值给了 number 类型的变量,类型不一致
let age: number = '18'

TypeScript类型概述

JS 已有类型

  • 原始类型,简单类型( number/string/boolean/null/undefined )
  • 复杂数据类型(数组,对象,函数等)

TS 新增类型

  • 联合类型
  • 自定义类型(类型别名)
  • 接口
  • 元组
  • 字面量类型
  • 枚举
  • void ...

TypeScript原始数据类型

原始类型:number/string/boolean/null/undefined

特点:简单,这些类型,完全按照 JS 中类型的名称来书写

let age: number = 18
let myName: string = '老师'
let isLoading: boolean = false
// 等等...

数组类型

数组类型的两种写法: 推荐使用 number[] 写法

// 写法一:
let numbers: number[] = [1, 3, 5]
// 写法二:
let strings: Array<string> = ['a', 'b', 'c']

    元组
let arr3 :[number , number,boolean]=[19,10,true]

联合类型

需求:数组中既有 number 类型,又有 string 类型,这个数组的类型应该如何写?

let arr: (number | string)[] = [1, 'a', 3, 'b']
  • 解释: | (竖线)在 TS 中叫做联合类型,即:由两个或多个其他类型组成的类型,表示可以是这 些类型中的任意一种
  • 注意:这是 TS 中联合类型的语法,只有一根竖线,不要与 JS 中的或(|| 或)混淆了
let timer: number | null = null
timer = setInterval(() => {}, 1000)
// 定义一个数组,数组中可以有数字或者字符串, 需要注意 | 的优先级
let arr: (number | string)[] = [1, 'abc', 2]

let obj:{a:1}|{b:'3'}; //表示 只能是a类型 值为1 或者b 类型 值为'3'   不能有其他属性

export{} :可以防止在另一个文件的变量定义后,本文件不能用,加上export{} 本文件中的变量名和其他文件的一样也可以用。

非原始类型 :

object (常用) Object()

let num1 :object = {a:1};

let num2: object = [1];

联合类型 :

往往一种类型不满足需求的时候我们会有混合的类型 进行解决

let arr :(number | string ) []  =[1,2.3,'abc']
//联合类型:|
//注意事项:|的优先级比较低,需要用() 包裹,一旦使用联合类型
//那么他们只能用他们共有的类型

timer = setInterval(() => {}, 1000)
// 定义一个数组,数组中可以有数字或者字符串, 需要注意 | 的优先级
let arr: (number | string)[] = [1, 'abc', 2]

类型别名

能够使用类型别名给类型起别

类型别名(自定义类型) :为任意类型起别名

使用场景:当同一类型(复杂)被多次使用时,可以通过类型别名,简化该类型的使用


//灵活度高,可以随意搭配使用
//形式一:
type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 'a', 3, 'b']
let arr2: CustomArray = ['x', 'y', 6, 7]
//形式二:
type custom =number | string 
let arr5:custom[]=[12,3,3,'abc']
//形式三:
type s = string
type n = number
let str :s = 'abc'
let str :n=23

解释:

1. 使用 type 关键字来创建自定义类型

2. 类型别名(比如,此处的 CustomArray )可以是任意合法的变量名称

3. 推荐使用大写字母开头

4. 创建类型别名后,直接使用该类型别名作为变量的类型注解即可

函数类型

能够给函数指定类型

函数的类型实际上指的是: 函数参数 返回值 的类型

为函数指定类型的两种方式: 1. 单独指定参数、返回值的类型

2. 同时指定参数、返回值的类型

1. 单独指定参数、返回值的类型:

// 函数声明
function add(num1: number, num2: number): number {
return num1 + num2
}
// 箭头函数
const add = (num1: number, num2: number): number => {
return num1 + num2
}

2. 同时指定参数、返回值的类型 :

type AddFn = (num1: number, num2: number) => number
const add: AddFn = (num1, num2) => {
return num1 + num2
}
  • 解释:当函数作为表达式时,可以通过类似箭头函数形式的语法来为函数添加类型
  • 注意:这种形式只适用于函数表达式

解决办法

https://www.cnblogs.com/CandyTT/p/13973676.html

// 需求: 自己定义一个可选参数的函数
  let str: string = '刘狄威真帅'
  console.log(str.slice()) // 从头截到尾: 刘狄威真帅
  console.log(str.slice(1)) // 从指定索引开始截取到末尾: 狄威真帅

   // 包含头部 不包含尾部
  console.log(str.slice(1, 4)) // 从指定索引开始截取到指定索引
  • 在 js 中定义了形参, 调用函数时可以不传实参, 非常灵活
  • 在 ts 中定义了形参, 调用时必须传入实参, 否则报错
  • 如果要实现可选参数, 加一个 ?

  // 注意事项: 必选参数不能在可选参数后 (符合常识)
  const print = (name?: string, gender?: string): void => {
    if (name && gender) {
      console.log(name, gender)
    }
  }

对象

给对象添加属性和方法

//对象类型
  let obj: {
    //哪些属性及其类型的声明
    name:string,
    age :number,
    gender:string,
    hobby:string 
    //定义函数
    sayHi:(content:string)=>void 
  }={
    //对属性的赋值
    name:'张三',
    age :23,
    gender:'未知',
    hobby:'喝水',
    sayHi(content){
      console.log('你好'+content)
    }
  }

从以上可以看出 ts代码 就像在写注释一样,特别容易明了内容

根据以上内容代码 我们为了复用性 ,可以把对象属性声明个类型,然后再有相似的我们就可以直接用类型去声明了,不用写更多的代码了

// 对象类型
  type Person = {
    name: string,
    age: number,
    gender: string,
    hobby: string,
    girlFriend?: string, // ? 表示可选属性
    // sayHi: (content: string) => void
    sayHi(content: string): void
  }

 // ts 就像在写注释, 以前写的注释是给程序员看的, ts 写的类型是给编辑器看的, 程序员也可以看
//对象1  
let obj1: Person = {
    name: '刘狄威',
    age: 38,
    gender: '未知',
    hobby: '圣杯布局',
    girlFriend: '乔碧萝',
    sayHi(content) {
      console.log('nihao:' + content)
    }
  }
//对象2
  let obj2: Person = {
    name: '某一帆',
    age: 66,
    gender: '未知',
    hobby: '黑卅导',
    sayHi(content) {
      console.log('你真别学了:' + content)
    }
  }
// 1,传统
  if (obj1.girlFriend) {
    obj1.girlFriend.concat()
  }

  // 2,优雅
  obj1.girlFriend && obj1.girlFriend.concat()

  // 3,最新: 可选链操作符, 前面有才会执行后面的函数
  obj1.girlFriend?.concat()
// axios({
  //   url: '',
  //   method: 'get', // 其他属性都不是必选项, 就可以用 ? 可选属性来实现
  //   data: {}
  // })

接口类型

一个对象类型被多次使用时,一般会使用接口( interface )来描述对象的类型,达到复用的目的 ,给对象约束属性和方法。

  • 1. 使用 interface 关键字来声明接口
  • 2. 接口名称(比如,此处的 IPerson),可以是任意合法的变量名称,推荐以 I 开头
  • 3. 声明接口后,直接使用接口名称作为变量的类型
  • 4. 因为每一行只有一个属性类型,因此,属性类型后没有 ;(分号)
// 作用: 给对象约束属性和方法
  // 基础语法:
  // interface 接口名 {
  //   属性名: 类型
  // }

  interface IPerson {
    username: string
    age: number
    gender: string
    sayHi: () => void
  }
  const p1: IPerson = {
    username: '刘狄威',
    age: 38,
    gender: '未知',
    sayHi() {
      console.log('我是榜一刘狄威, i\'m rich')
    }
  }

interface vs type

interface(接口)和 type(类型别名)的对比:

  • 相同点:都可以给对象指定类型
  • 不同点: 接口,只能为对象指定类型 类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名

推荐:能使用 type 就是用 type

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值