TS 从 小白 到入门 学习笔记

1.TypeScript介绍

文章目录

1.1TypeScript 是什么

TypeScript(简称:TS)是JavaScript的超集(JS有的TS都有)。

TypeScript= Type + JavaScript(在JS的基础上,为JS添加了类型支持)。

TypeScript是微软开发的开源编程语言,可以在任何运行JavaScript的地方运行。

// TypeScript 代码:有明确的类型,即: number (数值类型)
let age1: number = 18

// JavaScript 代码:无明确的类型
let age2 = 18

1.2TypeScript为什么要为JS添加类型支持

背景: Js的类型系统存在“先天缺陷”,Js代码中绝大部分错误都是类型错误(Uncaught TypeError) 。

问题:增加了找Bug、改Bug的时间,严重影响开发效率。

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

静态类型:编译期做类型检查;

动态类型:执行期做类型检查

代码编译和代码执行的顺序:1编译 2执行。 对于JS来说:需要等到代码真正去执行的时候才能发现错误(晚)

对于TS来说:在代码编译的时候(代码执行前)就可以发现错误(早)。并且,配合VSCode等开发工具,TS可以提前到在编写代码的同时发现代码中的错误,减少找Bug、改Bug时间

1.3 TS相比JS的优势

  1. 更早(写代码的同时)发现错误,减少找Bug、改Bug时间,提升开发效率。
  2. 程序中任何位置的代码都有代码提示,增强开发体验
  3. 强大的类型系统提升了代码的可维护性,使得重构代码更加容易
  4. 支持最新的ECMScript语法,优先体验最新的语法,让你走在前端技术的最前沿、
  5. TS类型推断机制,不需要在代码中的每个地方都显示标注类型,让你享受优势的同时,尽量降低成本。

    除此之外,Vue 3源码使用TS重写,Angular默认支持TS,React与TS完美配合,

1.4 安装编译 TS 的工具包

1.4.1安装命令

使用node,全局安装 TS 编译工具包

npm i -g typescript

1.4.2参看版本号

tsc -v

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

回答:Node.js/浏览器,只认识JS代码,不认识TS代码。需先编译为js代码后,再运行

typescript包的功能:把ts文件->js文件

1.5 编译并运行TS代码

1.5.1 整体步骤

  1. 创建hello.ts文件
  2. 将ts编译为js,在终端输入命令 tsc hello.ts(此时,在同级目录中会出现一个同名的hello.js文件)
  3. 执行js代码:在终端中输入命令node hello.js
第一步:先创建一个简单的hello.ts文件:
let uname:string = '张三'
console.log(uname)
第二、三步骤:在控制台执行依次执行命令:
tsc hello.ts
node hello.js

1.6 简化运行TS的步骤

问题:每次修改代码后,都要重复执行 两个命令,才能运行TS代码,太繁琐

简化方法:使用 ts-node 包,直接在 Node.js中执行ts代码。

安装命令:

npm i -g ts-node 

提示:ts-node提供了 ts-node命令

使用方式:ts-node ts文件

ts-node hello.ts

解释:ts-node命令在内部偷偷的将TS->JS,然后在运行JS代码。

注意:不会生成js文件,仅仅是在内部转换为js代码而已。

2.TypeScript的基本使用

2.1 TS的常用类型

2.1.1 TS的常用类型概述

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

  • 所有的JS代码都是TS 代码。

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

    如:1. 类型注解 2. 常用基础类型

2.1.2 类型注解

示例代码:

let age: number = 18
age=20
// age=‘张三’ // 报错:不能将类型‘string’分配给类型’number‘。

说明:代码中的 :number 就是类型注解。

作用:为变量添加类型约束。比如:上述代码中,约定变量age的类型为number(数值类型)

解释:约定了什么类型,就只能给变量赋值该类型的值,否则,就会报错。

2.1.3.0 TS常用基础类型

2.1.3.1 常用基础类型概述
可以将TS中的常用基础类型细分为两类:1 JS已有类型;2 TS 新增类型
  1. JS已有类型
    1. 原始类型:number/string/boolean/null/undefined/symbol(es6新增)。
    2. 对象类型:object(包括,数组,对象,函数等对象)。
  2. TS新增类型
    1. 联合类型自定义类型类型别名)、接口元组字面量类型、枚举、void、any等。
2.1.3.2 原始类型
1.类型名称:

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

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

2.类型使用:

yuansi.ts文件

let age: number = 18
let myName: string = 'zs'
let isLoading: boolean = false
let a: null = null
let b: undefined = undefined 
let s: symbol = Symbol()
2.1.3.3 数组类型
1.对象类型:object(包括,数组,对象,函数等对象)。
特点:对象类型,在TS中更加细化,每个具体的对象都有自己的类型语法
1.数组类型的两种写法:(推荐使用==number[]==写法)
2.书写测试的arr.ts文件
// 数组类型
let numbers: number[] = [1,2,5]
let strings: Array<string> = ['a','b','c']
2.1.3.4 联合类型
1.作用:多种类型的合集
2.使用场景:不是指定的单一类型时,可以使用 联合类型
3.书写测试的 lianhe.ts文件
// 联合类型 
//需求:数组中既有 number类型,又有string类型,如何写?
 //正确写法:
 let arr:	(number | string)[] = ['so',1,3,4,'app']
 // 错误写法:
 // let arr: number | string[] = ['so',1,3,4,'app'] //  报错,不能将number赋值给string
 // let arr: number | string[] = [1,3,4] // 不报错,但是不符合上面需求
 // let arr: number | string[] = ['so','app] // 不报错,但是不符合上面需求
 ---------------------------------------------------
 // 小括号的作用:
 // 加小括号:表示可以是 number或者string中任一类型数组。
 // 不加小括号: 表示只能是 | (竖线)左边的类型,或者是右边的类型。
解释:| (竖线)在TS中叫做 联合类型(由两个或多个其他类型组成的类型,表示可以这些类型中的任一类型)
注意:这是TS中联合类型的语法,只有一根竖线,不要与JS中的|或(||)混淆了。
2.1.3.5 类型别名(自定义类型)
1.作用:为任意类型起别名。
2.使用场景:当同一类型(复杂)被多次使用时,可以通过类型别名,简化该类型的使用
3.关键字: type
4.测试ts文件代码
// 1.非类型别名
// let arr: (number | string)[] = [1,'a',5,7,'opp']
// 2.类型别名
// 设置 类型别名
type CustomArray = (number | string)[]
// 使用  类型别名
let arr1: CustomArray = [1,'a',5,7,'opp']
let arr2: CustomArray = ['xyz',1,2,3]

解释:

  1. 使用 type 关键字来创建类型别名
  2. 类型别名(比如,此处的CustomArray),可以是任意合法的变量名称。
  3. 创建类型别名后,直接使用该类型别名作为变量的类型注释即可。
2.1.3.6 函数类型

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

1.用法: 为函数指定类型的两种方式

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

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

2.测试 ts 文件
// 方式1:单独指定参数,返回值类型
function add(num1: number, num2: number): number {
  return num1 + num2
}
const add2 = (num1: number, num2: number): number => {
  return num1 + num2
}
// 方式2:函数表达式的形式,同时指定参数,返回值类型
const add2: (num1: number, num2: number) => number = (num1, num2) => {
  return num1 + num2
}

注意:方式2:同时指定参数,返回值的类型,只适用于函数表达式

解释:当函数作为表达式时,可以通过类似箭头函数形式的语法来玩函数添加类型。

2.1.3.7 void类型
概述:如果函数没有返回值,那么,函数的返回值类型为: void
测试代码:
// void 类型默认可以不写
function getUser(name: string): void {
	console.log('Hello',name)
}
2.1.3.8 可选参数
1.🎅🏼概述:使用函数实现某个功能时,参数可以传也可以不传。
2.💖关键字: ?
3.✨用法:

​ 🤡可选参数:在可选可不传的参数名称后面添加 ? (英文问号)

​ 😈注意:可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数

4.🎃测试代码:
// 需求:做一个类似 数组的slice方法,可以slice()也可以slice(1)还可以slice(1,4)。
// 如下:
function mySlice(start?: number, end?: number):void {
	console.log('起始索引: ', start, '结束索引: ', end)
}
2.1.3.9 对象类型
1.🎅🏼概述:JS中的对象是由属性和方法构成的,而TS中对象的类型就是在描述对象结构(有什么类型的属性和方法)
2.🚀 语法: 使用 {}描述对象结构,属性采用属性名:类型的形式;方法采用方法名():类型的形式。
3.👏测试代码:
// 1.对象类型的单行写法:
// 提示: 需要用 ; (分号)隔开。
let person: {name: string; age: number; sayHi(): void; hobby(name: string): void} = {
	name: 'zs',
  age: 18,
  sayHi() {},
  hobby(name) {}
}
// 2.对象类型的多行写法:
// 提示1: 逗号 可以用,也可不用.
// 提示2: 多行写法,(不用逗号)每行建议只出现一个属性/方法,(用逗号)每行出现n个属性/方法都会不会报错
let person2: {
  name: string,
  age: number,
  sayHi(): void,
  hobby(name: string): void
} = {
	name: 'zs',
  age: 18,
  sayHi() {},
  hobby(name) {}
}
// 3.对象类型的箭头函数写法:
let person3: {
  name: string,
  age: number,
  sayHi()=> void,
} = {
	name: 'zs',
  age: 18,
  sayHi() {}
}
2.1.3.9 对象类型可选参数
💃 1.概述: 对象的属性或方法,也可以是可选的,此时需用可选属性了。
🎅🏼2.语法: 属性?:类型 ,在可选属性的右边添加问号即可。
🤡3.测试代码:
// 需求:我们在使用 axios({...})时,如果发送GET请求,method属性就可以省略。 
// 代码如下:
function myAxios(config: {url: string; method?: string}) {
  console.log(config)
}
// 总结: 可选属性的语法 与 函数可选参数的语法一致,都使用 ? (问号) 来表示。
2.1.3.10 接口
1.概述🎶: 当一个对象类型被多次使用时,一般会使用 接口(interface)描述对象的类型,达到复用的目的。
2.功能特点✨:
  1. 使用 interface 关键字来声明接口。
  2. 接口名称(比如,此处的Person),可以是任意合法的变量名称。
  3. 声明接口后,直接使用接口名称作为变量的类型
  4. 因为每一行只有一个属性类型,因此,属性类型没有==; (分号)==。
3.🎃测试代码:
// 设置 接口
interface Person {
  name: string
  age: number
  sayHi(): void
}
// 使用 接口
const person: Person = {
  name: 'zs',
  age: 18,
  sayHi() {}
}
// 提示: 接口建议首字母大写。
2.1.3.11 interface(接口) 和 type(类型别名)
1.两者的区别一😒:
(1)相同点😊: 都可以给对象指定类型。
(2)不同点😈:
  1. 接口: 只能为对象指定类型
  2. 类型别名: 不仅可以为对象指定类型,实际上可以为任意类型指定别名
(3)🎃测试:
//1设置 接口
interface Person {
  name: string
  age: number
  sayHi(): void
}
//1使用 接口
const person: Person = {
  name: 'zs',
  age: 18,
  sayHi() {}
}
//2设置类型别名
type Person2 = {
  name: string
  age: number
  sayHi(): void
}
//2使用类型别名
const person2: Person2 = {
  name: 'zs',
  age: 18,
  sayHi() {}
}
//3.类型别名 指定 任意类型
type ResData = (number | string)[]
2.1.3.12接口的继承:

🐱‍👤概述:(1)如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用

🎁关键字: extends

😎用法: 新接口 extends 要继承的旧接口

🎅🏼功能:接口实现复用

💕代码测试:

// 比如,这两个接口都有 x,y 两个属性,重复写两次,可以,但是繁琐
interface Point2D {x: number; y: number} 
interface Point3D {x: number; y: number; z: number}
// 改进:使用 extends 关键字
interface To2D {x: number; y: number} // 要继承的旧接口                
interface To3D extends To2D {z: number;}      

总结:

1.使用extends(继承)关键字实现了接口To3D继承To2D.

2.继承后,To3D就有了To2D的所有属性和方法.(此时To3D同时有x,y,z三个属性.)

2.1.3.13 类型别名的继承

🐱‍👤概述:(1)如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用

🎁关键字: &

😎用法: 新类型别名 = 旧类型别名 & 新增的类型

🎅🏼功能: 类型别名实现复用

💕代码测试:

// 旧类型别名 (要被继承的类型别名)
type P2D = {x: number; y: number}
//	P3D 继承了 P2D 的类型别名,并增加一个 z 属性的类型定义
type P3D = P2D & {z: number} 
2.1.3.14 元组
1.🌏场景:在地图中,使用经纬坐标来标记位置信息.
2.💦问题:可以使用数组来记录坐标,那么,该数组中只有两个元素,并且这两个元素都是数值类型.
3.🚗测试代码:
let position: number[] = [39.2324, 116.343234] 

使用number[]的缺点:不严谨,因为该类型的数组中可以出现任意多个数字.

4.概述❣: 元组(Tuple)

元组类型是另一种类型的数组,它确切地知道包含多少个元素,以及特定索引对应的类型.

5.元组的作用💥:
  1. 元组类型可以确切地标记出有多少个元素,以及每个元素的类型.

    明确数组中元素个数,以及索引对应的类型时,需要用到 元组.

6.代码测试💘💘💘:
let position: [number, number] = [39.4545, 48.89322]
2.1.3.15 类型推论(推断)

1.概述🔥:并不是所有的地方都要有类型注释,有两个地方,可以不使用类型注释,系统会自动进行 类型推断.

  1. 变量命名并初始化(图一)

  2. 决定函数返回值时(图二)

图一

​ (图一)

图二

​ (图二)

2.🌊代码测试:

// 声明变量并立即初始化值,此时,可以省略类型注解,
let age = 18
// age = '' // 报错,正常现象

// 注意: 如果声明变量但没有立即初始化值,此时,还必须手动添加类型注解
let a: number
a = 19
// a = '' // 报错,正常现象

// 错误写法: let a
// a = 15 
// a = '' // 不报错,非正常现象

//----------------	分割线 ------------------
// 当函数参数被类型注解时,如果没有写返回值类型,ts会自动触发 类型推断
function add(num1: number, num2: number) {
  return num1 + num2
}
// 注意: 返回值类型 是根据 return 后的参数的类型推断的而来的. 如果去掉 函数体里的内容,那么函数的返回值类型 为默认的 void类型.

注意🚀:这两种情况下,类型注解可以省略不写!

推荐⚡:能省略类型注解的地方就省略(偷懒,充分利用TS类型推断,提升开发效率)

技巧🏍:如果不知道类型,可以通过鼠标放在变量名称上,利用VSCode的提示来查看类型.

2.1.3.16 类型断言
1.🚀概述:在某些时候,当你比TS更明确一个值的类型时,可以使用 类型断言来指定更具体的类型.
2.⚓关键字: as
3.🛸使用:

html代码:

<a href='www.baidu.com' id='link'>点击去百度</a>

ts代码:

const aLink = document.getElementById('link') as HTMLAnchorElement
// 注意: getElementByld方法返回值的类型是HTMLElement,该类型只包含所有标签公共的属性或方法,不包含a标签特有的href等属性。
// 因此,这个类型太宽泛(不具体),无法操作href等 a 标签特有的属性或方法。
// 解决方式:这种情况下就需要使用类型断言指定更加具体的类型。

解释:

  1. 使用 as 关键字实现类型断言
  2. 关键字 as 后面的类型是一个更加具体的类型(HTMLAnchorElement 是 HTMLElement的子类型).
  3. 通过类型断言,aLink的类型变得更加具体,这样就可以访问a标签的属性或方法了.

另一种方法,使用<>语法,这种语法形式不常用,知道即可:

const aLink = <HTMLAnchorElement>document.getElementById('link')

4.注意点🌌:

问题:怎么知道 a标签的具体类型?

答案:(最笨的方法)在浏览器控制台,通过console.dir()打印a的标签,在属性列表的最后面,即可看到该元素的类型.

2.1.3.17 字面量类型
1.概述💦:某个特点的字符串也可以作为TS中的类型.
2.💧思考一下代码的类型推断,两个变量的类型分别是什么?

image-20230102141336398

(1).变量str1的类型为: string

(2).变量str2的类型为: ‘Hello TS’

解释:

​ 1.str1是一个变量 (let) ,它的值可以是 任意字符串,所以类型为: string

​ 2.str2是一个常量 (const),他的值不能变化只能是 ‘Hello TS’,所以,它的类型为: ‘Hello TS’

注意:除字符串之外,任意的JS字母量(比如,对象.数字等)都可以作为字面量类型使用.

3.使用模式🛴:字面量类型配合联合类型一起使用.
4.使用场景🛫: 用来表示一组明确的可选值列表.比如:在贪吃蛇游戏中,游戏的方向的可选值只能是上下左右中的任意一个.
5.代码测试🪐:
function changeDirection(direction: 'up' | 'down' | 'left' | 'right') {
  console.log(direction)
}
// 提示: 参数direction的值只能是 up/down/left/right 中的任意一个.
// 优势: 相比于 string 类型,使用字面量类型更加精确,严谨.
2.1.3.18 枚举
1.概述🪂:枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值.
2.枚举:定义一组命名常量.它描述一个值,该值可以是这些命名常量中的一个.
3.关键字💥: enum
4.代码测试🚀:
// 定义 枚举
enum Direction { Up, Down, Left, Right }
// 使用 枚举
function changeDirection(direction: Direction) {
	console.log(direction)
}
// 怎么使用枚举里的实参?
// 答案: 类似于 JS中的对象,直接通过 点(.)语法 访问枚举的成员.
changeDirection(Direction.Up)// 枚举.属性名
5.注意🔥:
  1. 使用 enum 关键字定义枚举.
  2. 约定枚举名称,枚举中的值大写字母开头.
  3. 枚举中的多个值之间通过==,(逗号)分割==.
  4. 定义好枚举后,直接使用枚举名称作为类型注释.
6.给枚举的实参设置值 被称为 数字枚举

问题🐱‍👓:我们把枚举成员作为了函数的实参,它的值是什么呢?

答案:通过将鼠标移入 Direction.Up,可以看到枚举成员Up的值为0.

注意:枚举成员是有值的,默认为:从0开始自增的数值.

我们把,枚举成员的值为数字的枚举,称为: 数字枚举.

当然,也可以给枚举中的成员初始化值.

测试代码🎃:

// 枚举成员设置 初始值
enum Direction { Up = 10, Down, Left, Right} // 那么 Down为11,Left为12....
enum Direction { Up = 2, Down = 4, Left = 8, Right = 16}
7.字符串枚举
1.概述🎉🎉🎉:枚举成员的值是字符串.
2.注意🎗🎗🎗:字符串枚举没有自增长行为,因此,字符串枚举的每个成员必须有初始值.
3.测试代码🎈🎈🎈:
// 给枚举成员 赋值 字符串
enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT'
}
8.编译枚举
1.概述🧧:枚举是TS为数不多的非JavaScript类型扩展(不仅仅是类型)的特性之一.
2.原因👓:因为其他类型仅仅被当做类型,而枚举不仅用作类型,还提供值(枚举成员都是有值的).也就是说,其他的类型会在编译为JS代码时自动移除.但是,枚举类型会被编译为js代码!

如下图:

image-20230102191210885

3总结🏆🏆🏆:

枚举与前面讲到的字面量类型+联合类型组合的功能类似,都用来表示一组明确的可选值列表.

一般情况下,推荐使用字面量类型+联合类型组合的方式,因为相比枚举,这种方式更加直观.简洁.高效

2.1.3.19 any 类型
原则👓:不推荐使用any!因为当值的类型为any时,可以对该值进行任意操作,并且不会有代码提示.

image-20230102194241577

解释🏐🏀🥎:以上操作都不会有任何类型错误提示,即使可能存在错误!

​ 尽可能的避免使用any类型,除非临时使用any来避免书写很长,很复杂的类型!

其他隐式具有any类型的情况🎭:
  1. 声明变量不提供类型也不提供默认值
  2. 函数参数不加类型
注意💋:因为不推荐使用any,所以,这两种情况下都应该提供类型!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海424

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值