【D1n910前端学习笔记】TypeScript完全解读(2/26) 02-基础类型
正常操作,正常分析,大家好,我是D1n910

上期内容是

相比起来,这期会显得有些“无聊”,啊哈哈,因为我之前自学过大部分的内容,所以基础类型的我已经过过了,希望Lison老师能给我一些不一样的内容~
现在开始

TypeScript完全解读(2/26)基础类型
0 核心内容
布尔值
数值
字符串
数组
元组
枚举值
any
void
null和undefined
never
object
类型断言
0.1 预备工作
在上一节课的项目里,`src`下新建一个文件夹`example`,以后上课的例子,一般都放到`example`里

这节课先创建一个`base-type.ts`文件

我们通过VScode来开发ts项目,可以下载一些插件,比如 `tslint`,这样可以有很好的代码提示

我们把项目跑起来(`npm start`),当我们需要看到值或者结果时,我们可以在浏览器的控制台查看结果

正式开始——
1、布尔类型(boolean)
布尔类型只有两种值(true/false)
在ts中声明布尔值如下

这个有什么作用呢?
比如我们把一个非布尔类型的值赋值给刚刚定义的布尔类型的变量,会有提示有问题,且会告诉你具体有什么问题。
这边就会提示不能将类型“123”分配给类型“boolean”(这边“134”这么又会是一个类型呢,后 面会说这种类型)

我们还可以这么声明变量

2、数值类型(number)
数值类型的声明是 `number`

ts支持es6的新增的二进制和八进制的字面量进行赋值

3、字符串类型(string)
支持普通的字符串赋值,也支持模版字符串

这里的打印方法想要被执行,我们可以在入口文件`index.ts`中引入`base-type.ts`
import './example/base-type.ts'

保存后在控制台可以看到对应输出

4、数组类型
数组类型的定义有两种写法
以数值数组类型(例子 [1, 2, 3])
4.1、写法1
`let arr:number[]`
我们可以这么赋值
arr = [1, 2, 3] // 正确
如果我们这么赋值:
arr = [1, 'a', 2] // 报送类型错误
4.2、写法2
let arr2:Array<number> // 意思是指定一个数组类型,然后其中是number元素
4.3、联合类型:数组中写多种类型
我们的数组不一定就存储一种类型,这时候,我们可以使用联合类型
比如我们指定既可以是string又可以是number类型
let arr3:(string | number)[]
通过这样的方法,我们可以这么赋值
arr3 = [1, 'a']
记住需要加入括号,如果不加入括号的话,即为let arr3:string | number[],ts会理解为既可以是arr3既可以是string类型,又可以是数值数组类型。
本小节涉及代码

5、元组类型
大家可能听得不多元组。
他在ts的作用类似数组,但是是数组的拓展。和数组的区别在于。
数组:指定了元素的类型,就可以随便往里添加任意数量符合元素类型的值
元组:区别在于,固定长度,固定类型。
这里我们简单定义一个元祖类型
let tuple: [string, number, boolean]
我们这么定义后,必须要按照顺序、类型来赋值
tuple = ['a', 2, false] // 正确
// 少了不行
tuple = ['a', 1] // Property '2' is missing in type '[string, number]' but required in type '[string, number, boolean]'.
// 不对应类型的不行
tuple = ['a', 1, 2] // 不能将类型“number”分配给类型“boolean”
// 多了类型的不行
tuple = ['a', 1, false, 2] // 不能将类型“[string, number, false, number]”分配给类型“[string, number, boolean]”。 属性“length”的类型不兼容。 不能将类型“4”分配给类型“3”。
// 可以和数组类型一样指定下标赋值
tuple[2] = true // 正确
// 指定下标赋值也要正确对应的类型
tuple[2] = 1 // 不能将类型“1”分配给类型“boolean”
本小节涉及代码

6、枚举类型
这个如果我们有接触过C++类型的语言,那么会比较熟悉。我们会定义一些名字,然后每一个名字对应一个索引值。
在ts中,也加入了枚举。
使用 `enum` 来定义枚举。
假设我们定义了一组权限值,比如“超级管理员”、“管理员”、“用户”
下面就是基础的枚举值的名字,我们习惯于把枚举值的变量名首字母大写
enum Roles {
SUPER_ADMIN,
ADMIN,
USER
}
我们可以直接这么使用
console.log(Roles.SUPER_ADMIN) // 0
console.log(Roles.ADMIN) // 1
console.log(Roles.USER) // 2

能看到打印出序列号,这序列号是自动的。
这个枚举类型有什么作用呢?
举一个简单的场景:
我们需要根据后端返回的用户类型执行对应的代码,比如后端返回用户类型types的值为0,代表超级管理员,我们会这么写代码
if ( types === 0 ) {
// 执行一些代码
}
// types === 0 不是很明显知道这代表了什么,但是如果用上了枚举类型,那么我们可以这么做
if ( types === Roles.SUPER_ADMIN ) {
// 执行一些代码
}
// 这样看起来就好很多了
咱们的序列号可以是自动的,也可以是自定义的
enum Roles {
SUPER_ADMIN = 1,
ADMIN = 3,
USER
}
这边我们进行打印以后会发现得到的结果,SUPER_ADMIN 和 ADMIN都是对应的值,而USER则是在ADMIN上自动加一位。

我们可以通过枚举的名称找到索引值,也可以通过枚举的索引值找到对应的名称

注意⚠️:ts是一个翻译机,那么这个枚举类型翻译成js代码是这么实现的呢?
以
enum Roles {
SUPER_ADMIN,
ADMIN = 4,
USER
}
为例子,在typesscript翻译后,会变成
var Roles;
(function (Roles) {
Roles[Roles["SUPER_ADMIN"] = 0] = "SUPER_ADMIN";
Roles[Roles["ADMIN"] = 4] = "ADMIN";
Roles[Roles["USER"] = 5] = "USER";
})(Roles || (Roles = {}));
// 我们可以用这个typescript的线上编译器 http://www.typescriptlang.org/play/index.html 来查看翻译后的内容
// 这边运用到了一个小知识点是,对象属性赋值操作的表达式其实是个隐藏了会返回赋值的内容的情况

// 在这里的设计非常巧妙,即设置了属性对应序号,又设置了序号对应属性;所以我们可以经常看看typescript的大佬这么翻译的,学学大佬的代码
7、any类型
javascipt是非常灵活的,我们的数据或者一些逻辑可能要运行的时候才能确定类型,写代码的时候是不知道类型的,那么这时候我们就需要指定我们的类型为any。
我们赋任意类型的值。

对于数组类型的元素也可以是any

这么方便的类型,我们是不是在什么地方都用any呢?
那这样的话,我们就没有用ts的意义了。
any是能不用就不用。
* 如果不给变量指定类型,会隐式地指定为any类型

8、void类型
void和any类型相反,void的意思就是什么类型也不是
一般我们常用来定义一个不会返回任何值的函数

具体函数相关的内容,会在后面讲函数的时候涉及。
在JavaScript中,一个函数如果没有指定返回内容,那么默认会返回undefined
那为什么这边可以定义咱们这个函数返回值类型为void呢?
因为在ts中,void类型可以被赋给undefined以及null

这里我们发现赋值null给void类型的时候,有报错`不能将类型“null”分配给类型“void”`
原因是我们生成的ts的配置文件`tsconfig.json`中,我们直接生成后,没有对里面的内容做修改。我们在后面的项目配置一块会详细地讲项目配置内容,现在简单看看。

这些选项是用来控制【严格检查代码】的。
比如`strictNullChecks`就是涉及到了我们刚刚的报错问题。我们把这个配置项设定为false,即关掉。

就可以看到不会有报错了。

* 注意,我们修改了`tsconfig.json`,需要重新npm start
9、null和undefined类型
ts定义undefined类型后
let u: undefined
这个u变量就只能被赋给undefined或者null的值了

同样的,ts定义null类型后
let u: null
这个u变量就只能被赋给undefined或者null的值了

undefined、null能相互赋值的原因是因为本身它们就是类型的子类型

但是如果我们把刚刚`strictNullChecks`选项打开

就会代码严格,报错提示只能赋值给对应类型

一般来说我们为了让代码更规范,会把严格模式都打开。
10、never类型
表示的是永远不存在的值的类型
【抛错误情况】
比如一个函数执行后会一定会抛出错误,那么它永远不会有返回值

【死循环,永远没有返回值情况】

never类型的值是任意类型的子类型 —— never类型的值可以赋值给任意类型
没有任意类型的值是never类型的子类型——除了never 类型的值,其他类型都不能赋给never类型。
这里我们通过使用必包创建一个never类型的变量,印证了我们的规则。

11、object类型
object类型就是对象类型,在js中和其他基础类型不一样,其他的一些数值类型、字符串类型是直接存值,而object是存的是内存中地址的引用。
ts中可以指定一个值的类型为对象类型

12、类型断言
有时候ts并没有了解一个值的真实类型,我们希望这个类型检查由我们自己进行,我们自己知道这个值是什么类型。那这个类型断言有点像类型转换,它可以根据某个值强行转换为我们需要的值。
比如我们可能传入的值是数值类型的,也可能是字符串类型的,而我们要返回传入值的字符长度,写下面的一个方法
const getLength = target => {
if (target.length || target.length === 0) {
return target.length
} else {
return target.toString().length
}
}
在ts中,如何进行类型定义呢?
首先,我们的第一行,定义传参是联合类型,可能是string也可能是number,返回的类型当然是number
但是这会有一个问题,传参能调用的方法,必须是联合类型的交集方法,即要都有才能使用。

这边我们知道,其实我们的函数逻辑是没错的,但是ts有类型判断,所以会这样。
我们可以通过类型断言解决,有两种写法
(1)尖括号+括弧形式

(1)变量名 as 类型形式

这两种类型断言都可以
最终添加了类型断言的如下所示

我们发现,每次这边用到string方法的target都要定义一下,很麻烦,后面我们会学到高阶类型自定义保护,到那个时候,只需要做一次类型保护即可。
* 如果我们使用jsx的写法的话,我们只能使用 as 的方法

完毕
腰酸背痛……看视频学基础太痛苦了……困死……
本小节仓库地址
https://github.com/D1N910/ts-learning/tree/master/02

恭喜你获得称号
了解typescript基础类型的勇士
你的学习进度(2/26)
▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇ ▇▇

声明
本系列内容是D1n910通过学习Lison老师的TypeScript完全解读(26课时)整理的文字笔记,如果看完后觉得有收获,抑或想要直接支持,抑或想要直接视频原版内容,请直接到https://segmentfault.com/ls/1650000018455856?r=bPXT7X。

虽然本系列是笔记,但是也有D1n910的心血所在,请勿在未告知D1n910及获得D1n910允许的情况下直接转载本笔记——如果您是基于笔记又生成您自己的笔记,这是一点问题都没有的~