TypeScript系统学习指南

1、什么是TypeScript?

为了解决JavaScript经常出现的类型错误而出现的TypeScript。

TypeScript: JavaScript程序的静态类型检查器,一个在代码运行之前运行的工具。 确保了代码的类型正确,本质上添加了可选的静态类型基于类的面向对象的编程。

2、为什么要使用TypeScript?

JavaScript的每一个值(可能是个字符串、可能是个对象、可能是个方法),都有它们的行为,但会有这么几个问题⬇️

2.1类型错误

message.toLowerCase()
message()

这两句代码有什么问题吗?一个字符串转成小写,一个调用message方法。
不确定message是什么就是最大的问题了!
如果message是个字符串,第二个方法调用就会出现TypeError的错误了!
所以我们需要一个静态类型检查器

2.2无法预测函数会做什么

function fn(e){
	return e.method()
}

上边这个函数执行成功的条件就是参数e得有一个可以执行的method方法,但是,如果不实际的跑一跑代码,没法知道他是否能正常工作

总结: javascript只能动态的检查错误(即,代码跑起来才知道错误),所以我们需要一个静态的检查TypeScript,在代码跑之前就把有可能发生问题都给毙掉。

3、TypeScript的基础使用

3.1 静态类型检查

看一下2.1提出的问题在TypeScript是怎么提示我们的:
在这里插入图片描述
Error:字符串类型的表达式不能被调用
在这里插入图片描述
Error:message函数上不存在属性toLowerCase

总结:在我Run代码之前,TypeScript就已经把我的问题抛出来了,这就是静态类型检查器。

3.2 非异常故障

非异常故障:合法的错误,举个例子

const person = {
	name:"ts",
	age:"18"
}
person.name //ok的,ts
person.home //ok的,undefined

看,问题出现了,person的home,根本没有定义,但是返回的是一个undefined,我都没定义你怎么能用呢,虽然这在js里是可以的,但他是合法的错误,为了我们代码的健壮性,就得把这些非异常故障给规避掉。看TS是怎么规避的⬇️
在这里插入图片描述
Error:在这个类型上不存在属性home

其他非异常故障:

  • 检查拼写错误
    调用一些方法的时候不小心输错了⬇️
    在这里插入图片描述
    Error:在message上不存在toLocaleUpperCas属性,你是想用toLocaleUpperCase吧!
  • 未调用函数
    函数需不需要调用,Ts能检查一下⬇️
    在这里插入图片描述
    Error:运算符">“不能被应用于function上
    这里TS检查出来了你要用运算符”>",那你就不能是function
  • 基本逻辑错误
    在这里插入图片描述
    Error:
    1、始终返回false,因为"a"和"b"没有重叠
    2、始终返回true,因为"a"或"b"和"1"没有重叠
    解释一下:
    1、等于"a"和等于"b"一码事,所以没有重叠(if…else)了
    2、不等于"1"在逻辑上就一定是true,因为num只能是"a"或"b",所以没有重叠(if…else)了

4、开发工具

编辑器——VSCode
JS运行环境——NodeJS
TypeScript编译器——npm install -g typescript
在这里插入图片描述
VSCode相关TS插件⬇️

5、实际使用

5.1简单看一下TS的使用效果

在这里插入图片描述
快看,TS告诉我了Error:1、test函数里没有data这个变量。2、我调用test函数,得有两个参数。
OK,补充修改一下,然后再执行⬇️
在这里插入图片描述
编译完出现了新问题,看一下⬇️
在这里插入图片描述
这里就引申出两个问题:

  • ts编译成js之后,ts和js里都有个test(),方法名重复了!(关掉js就没了,但是这是掩耳盗铃哈,可不能到时候好几个ts文件,里面的方法名都是重复的。)
  • 每次ts更改完都要手动编译(tsc)一下

5.2编译使用优化

5.2.1解决TS、JS变量或函数名重复冲突问题

tsc --init 生产配置文件
在这里插入图片描述

5.2.2自动编译

tsc --watch
在这里插入图片描述

5.2.3错误时不发出(编译)

tsc -noEmitOnError
默认是false,如果打开了,ts文件有错的话就不会编译输出成js文件了
官网是这么说的>
看一下TS有错误了⬇️
在这里插入图片描述TS文件有错误,还是能编译成JS,JS也有相同的问题了⬇️
在这里插入图片描述
这里就出现了3.2所说的合法的错误,这种情况(underfined)出现在前端肯定是不行的🙅‍♂️
打开noEmitOnError⬇️
在这里插入图片描述
然后先把ts改成正确的
在这里插入图片描述
我们再改成错误的,会发现没有把错误的ts编译成js
在这里插入图片描述
当然,我们不能每次都用命令去noEmitOnError呀,这就要说的我们之前的那个生产配置文件了(tsconfig.json),我们在里面把noEmitOnError设置成True就不用在终端跑tsc -noEmitOnError命令了。
在这里插入图片描述

5.3显式类型

还记得5.2.1中生存配置文件后出来的新问题吗,我们来解决它。

显式类型手工的给它们去定义类型

在这里插入图片描述

5.4降级编译

大家看一下5.1的第二个图和上边这张图,有没有发现编译后的js文件有些不同,5.1称为a,上图称为b。
1、b的console.log里面是es6的语法,a却是浏览器兼容更好的基本语法。
2、b是tsc --watch监听的,a是tsc 文件名手动编译的,这难道有什么不一样吗?

原因:配置文件告诉TS编译的目标(Target)JS是es6就行,所以我们编译之后的JS文件就是有ES6语法的。

更改配置文件⬇️
在这里插入图片描述

总结:这个把高版本的ECMAScript向下移动到旧版本的ES的过程,就是降级

5.5严格模式

还记得5.2.1中创建配置文件的时候新出现的错误吗,在显式类型中我们已经把它解决了,但是一开始我们是在配置文件中关掉了严格模式才让ts不检查这类错误的。

Tips:虽然打开严格模式会使我们编写更多的代码,但是从长远来看,他是值得的。

TypeScript有三个严格检查的标记:

  • strict:严格模式
    —不建议把严格模式关掉(strict:false),否则就失去了用TypeScript做类型检查的意义。
  • noImplicitAny:不要隐式的any类型
  • strictNullChecks:检查值为undefined和null的变量并抛出错误
    —因为undefined和null不加以判断是造成大部分错误的元凶,所以直接检查抛出错误

Tips:strict等价于noImplicitAny和strictNullChecks同时打开

在这里插入图片描述

6、TypeScript的基本类型

6.1类型介绍

  • 常见的原始类型:
    1、string—表示字符串值,如"Hello, world"。
    2、number—表示数字,如520。JS没有int或float,一切都只是number。
    3、boolean—true和false

注意:在ts里,string和String是不同的,string是我们平常理解的字符串类型,而String是一个构造函数⬇️
同理,boolean和Boolean、number和Number
在这里插入图片描述 Error:‘string’ 是一个原始的,但 ‘String’ 是一个包装对象。 尽可能使用“string”。
Tips官方解释:类型名称String, Number, 和Boolean(以大写字母开头)是合法的,但指的是一些很少出现在代码中的特殊内置类型。始终使用string、number或boolean表示类型。

  • 不常见的原始类型:
    1、bigint—非常大的整数,ES2020开始支持
    2、symbol—全局唯一引用
  • array:数组类型—[1, 2, 3]
  • any:任意—不希望ts检查这个值,就使用any
  • object:对象类型—非原始类型,对象可能包含任意类型
  • enum:枚举类型—允许描述一个值,该值可能是一组可能的命名常量之一
  • undefined:undefined
  • null:null
  • never:不存在的值的类型

6.2类型使用

6.2.1原始类型

在这里插入图片描述

6.2.2数组类型

在这里插入图片描述

6.2.3any类型

在这里插入图片描述

6.2.4变量和函数的类型注释

前三个内容就是变量的类型注释,其实它们也可以不写,因为ts可以自己推断⬇️
在这里插入图片描述
函数的类型注释也一样,不过它有参数的类型注释返回值的类型注释⬇️
在这里插入图片描述

在开发过程中,有些地方需要类型注释,有些地方就不需要,不用每个地方都加上类型注释

6.2.5对象类型

带有任何JS的值,都可以看成是对象
在这里插入图片描述

6.2.6联合类型

那我一个值有可能string也有可能是number怎么办,用any吗?

联合类型:两个或多个类型组成的类型

在这里插入图片描述

Tips:这里的函数的返回值的类型注解都没有写,ts自己推断了

6.2.7类型别名—type

上边的类型定义都是直接在定义值的时候定义的,那能不能拿出来呢,这样如果多次使用同一种类型的时候也方便。

类型别名:给你想要的类型定义一个名字,以后用这个名字来代替定义的类型
语法:type 别名 = 类型,别名首字母大写

在这里插入图片描述

6.2.8接口—interface

接口:是一种结构类型,用来定义对象类型的另一种方式
语法:interface 接口名 {},接口名首字母大写

在这里插入图片描述

6.2.9接口interface与类型别名type的区别

  • 接口只能定义对象类型,类型别名可以定义所有类型
  • 扩展方式不同⬇️
    在这里插入图片描述
  • 向现有的类型中添加字段方式不同⬇️
    在这里插入图片描述

6.2.10类型断言

获取一个值,但是不知道这个值是什么类型,就可以使用类型断言。

类型断言: 我不知道你是啥,但我先给你断一下。
作用: 很有用哦,在我们写代码不知道这个值是什么类型的时候,可以先断言为一个差不多的类型

语法:

  • as
const 变量名 = 不知道的类型的值 as 我给你断一个string吧
const my = buzhidao as string
// dom节点也有属于自己的Element类型,比如canvas节点就是一个HTMLCanvasElement类型的节点
const myCanvas = document.getElementById("my-canvas") as HTMLCanvasElement
  • <>
const 变量名 = 不知道的类型的值 as 我给你断一个string吧
const my = <string>buzhidao
// dom节点也有属于自己的Element类型,比如canvas节点就是一个HTMLCanvasElement类型的节点
const myCanvas = <HTMLCanvasElement>document.getElementById("my-canvas")

Tips:TS只允许类型断言转化为更具体的类型或不太具体的类型
作用:防止不可能(无重叠)的强制断言(string断成number,string和number无重叠,any和number有重叠)

在这里插入图片描述

6.2.11文字类型

特定的位置定义特定的字符串和数字,可以简单的理解成JS定义常量的const

  • 文字字符串类型
    在这里插入图片描述

  • 文字数字类型

// 还可以用在函数返回值的类型注释,文字数字类型
function fn(a: string, b: string): -1 | 0 | 1 {
  return a===b?-1:a>b?0:1
}
  • 文字布尔类型-只有两种:true、false
// 只能是true、false
let texttrue: true = true
let textfalse: false = false
  • 混合(文字类型和其他类型)
// 混合,文字类型和其他类型混合使用
interface Options {
  width: number
}
function config(x: Options | 'auto'){

}
config({width:520});
config('auto')
  • 文字类型推断

在这里插入图片描述

6.2.12undefined和null类型

JavaScript 有两个原始值用于表示不存在或未初始化的值null和undefined
TypeScript 有两个对应的同名类型。
在这里插入图片描述

6.2.13枚举类型

你确定要使用它,要不然没必要使用

在这里插入图片描述

6.2.14bigint和symbol—不常用的原始类型

  • bigint:非常大的整数,ES2020开始支持
  • symbol:全局唯一引用,通过函数创建

在这里插入图片描述

7、类型缩小

在联合类型中,因为类型不同,导致处理结果也会不对,所以就要分开处理。
类型缩小:一个过程,通过各种方式方法,将类型细化成比声明更具体的过程称之为类型缩小

举例:声明了一个联合类型,有number和string,在代码处理过程中,当是number怎样处理,当是string怎么处理,这个过程就是类型缩小
在简单点说,就是类型判断,然后做不同的事情
感觉没什么用啊,不就是js的类型判断吗,但是官网抽出来讲了,不知道为啥。

7.1typeof类型保护

通过typeof进行类型的检查判断,从而确保代码的稳定

就是通过typeof 判断类型是string还是number还是object还是其它

function printAll(strs: string | string[] | null) {
  if (typeof strs === "object") {
    for (const s of strs) { // 这里会有一个报错哦,因为null的类型也是object
      console.log(s);
    }
  } else if (typeof strs === "string") {
    console.log(strs);
  } else {
    // do nothing
  }
}

7.1.1TS的typeof类型

“string”、“number”、“bigint”、“boolean”、“symbol”、“undefined”、“object”、“function”

7.2真值缩小

就是判断这个值是不是真的

还记得7.1的报错,null是object,那我们就可以再加一个真值缩小

function printAll(strs: string | string[] | null) {
  if (strs && typeof strs === "object") { // 这里判断了strs存在(不为null)
    for (const s of strs) {
      console.log(s);
    }
  } else if (typeof strs === "string") {
    console.log(strs);
  }
}

和JS中一样,做ture/false判断的表达式:if、&&、||、!

false的情况:0、NaN、“”(空字符串)、0n(bigint零版本)、null、undefined

除此之外,有两种不常见的强制转化为true的方式

  • Boolean(“hello”); >> 转化后,类型是boolean类型,值是true
  • !!“world”; >> 转化后,类型是文字布尔类型(6.2.11),值是true

7.3等值缩小

使用switch语句和相等性检查,如== 、!==、==和!=来缩小类型。

function example(x: string | number, y: string | boolean) {
  if (x === y) {
  	// 全等判断,数值相等,类型也相等,x和y类型相等的情况只有一种,就是string
    // We can now call any 'string' method on 'x' or 'y'.
    x.toUpperCase();
    y.toLowerCase();          
  } else {
    console.log(x);
    console.log(y);
  }
}

除了全等于,还有更宽松的==,比如:undefined==null

7.4运算符in缩小

JS中的运算符in用于确定一个对象是否具有某个名称的属性

type Fish = { swim: () => void };
type Bird = { fly: () => void };
 
function move(animal: Fish | Bird) {
  if ("swim" in animal) { //如果animal有swim属性,那么就有swim()
    return animal.swim();
  }
 
  return animal.fly();
}

7.5运算符instanceof缩小

JS中的运算符instanceof用来检查一个值是否是另一个值的“实例”

实例的概念,new 一个实例:let date = new Date() // 这里变量date就是日期函数(或类)的一个实例

function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString());
  } else {
    console.log(x.toUpperCase());               
  }
}

7.6赋值缩小

在为变量赋值过程中,TS可以查看等号右边的内容并适当的缩小内容再赋给左边变量。

let x = Math.random() < 0.5 ? 10 : "hello world!";
// x有可能是number、有可能是string,即联合类型
x = 1;
console.log(x);
x = "goodbye!"; 
console.log(x);

7.7控制流分析

怎么个控制流分析,看代码⬇️

function example() {
  // 这里定义了x是联合类型,string|number|boolean
  let x: string | number | boolean;
  x = Math.random() < 0.5;//到这里,x应该是boolean类型的了

  // if判断
  if (Math.random() < 0.5) {
    x = "hello"; // 到这里是string
    console.log(x);     
  } else {
    x = 100; // 到这里是number
    console.log(x);     
  }
  return x; //现在返回的x是什么类型呢?猜一下
}

let x = example()
x = "string" //ok,没错
x = 520 //ok,没错
x = true //出错了

// 这说明,函数里到x从一个三个类型的联合类型变成了两个类型(string|number)的联合类型
// 这就是控制流分析,经过流程分析出结果到底是什么类型,或者说有哪些类型是不需要的,去掉它,缩小范围

7.8类型谓词

有时更想直接的控制整个代码的类型结构,而不是单独控制某个参数的类型。

语法:function fn(参数: 类型1 | 类型2): 参数 is 类型1
解释:当返回值为true时,参数的类型为类型1,反之为类型2,这里的类型1类型2是type或interface定义的对象类型

在这里插入图片描述
用这种类型判断(函数isFish)去过滤数组

// 定一个Fish和Bird类型混合的数组
const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()];
// 现在来过滤这个数组,把Fish类的都过滤出来了
const underWater1: Fish[] = zoo.filter(isFish);
// or
const underWater2: Fish[] = zoo.filter(isFish) as Fish[];

更仔细的过滤

// 不要name是sharkey的Fish类
const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
  if (pet.name === "sharkey") return false;
  return isFish(pet);
});

7.9受歧视的unions

在这里插入图片描述

7.10never类型与穷尽性检查

never:不应该存在的状态
当我们类型缩小,缩小到什么都没有的情况,就是never。

never可以分配给任何类型,但是没有类型可以分配给never,这意味着可以使用缩小范围并依靠never出现在 switch 语句中进行详尽的检查(还有没有遗留的没处理)。

在这里插入图片描述

8、函数

9、对象类型

10、类型操作

11、类

12、模块

13、TS配置文件参数详解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值