正缩胃技多不压身,不多逼逼,直接开学。 注:本系列文章参考阮一峰老师的教程。
前言
今天我们来学习 TypeScript 中的 类型。
类型的概念
类型指的是具有共同特征或属性的一类对象或元素。
eg:123和234共同特征是都能进行数值运算,属于数值(number)这个类型。
一旦确定某个值的类型,就意味着,这个值具有该类型的所有特征,可以进行该类型的所有运算。凡是适用该类型的地方,都可以使用这个值;凡是不适用该类型的地方,使用这个值都会报错。
可以这样理解,类型是人为添加的一种编程约束和用法提示。 主要目的是在软件开发过程中,为编译器和开发工具提供更多的验证和帮助,帮助提高代码质量,减少错误。
小demo
接下来我们请出代码界的李华——"Hello World!"。
const hello : string = "Hello World!"
console.log(hello)
你或许会好奇,这里的: string是什么?我们再看一个例子:
function add(n:number) {
return n + 1;
}
add('hello') // 报错
我们在定义函数 add 的时候,形参给的n:number,在调用时,传了一串字符串作为实参,结果报错了。这就是 ts 为 js 变量加上了类型声明。
类型声明
- 类型声明写法:在标识符后面添加“冒号 + 类型”。
值得注意的是,在 js 中,当一个变量未定义(变量已经声明但尚未赋值),访问这个变量是不会报错的,而在 ts 中,这一行为则会导致错误发生。
但是如果我写成这样呢?
let a
console.log(a)
这里涉及到了TS中的any 类型。
类型推断
类型声明并不是必需的,如果没有,TypeScript 会自己推断类型。(我不要你觉得,我要我觉得😎)
在上述代码中,Typescript 判断 a 的类型为number,在后续的赋值中,如果是其他的类型,则会报错。
TypeScript 也可以推断函数的返回值。
Typescript 的编译
JavaScript 的运行环境(浏览器和 Node.js)不认识 TypeScript 代码。所以,TypeScript 项目要想运行,必须先转为 JavaScript 代码,这个代码转换的过程就叫做“编译”(compile)。
TypeScript 官方没有做运行环境,只提供编译器。编译时,会将类型声明和类型相关的代码全部删除,只留下能运行的 JavaScript 代码,并且不会改变 JavaScript 的运行结果。
因此,TypeScript 的类型检查只是编译时的类型检查,而不是运行时的类型检查。一旦代码编译为 JavaScript,运行时就不再检查类型了。
值和类型
学习 TypeScript 需要分清楚“值”(value)和“类型”(type)。
“类型”是针对“值”的,可以视为是后者的一个元属性。每一个值在 TypeScript 里面都是有类型的。比如,3是一个值,它的类型是number。
TypeScript 代码只涉及类型,不涉及值。所有跟“值”相关的处理,都由 JavaScript 完成。
这一点务必牢记。TypeScript 项目里面,其实存在两种代码,一种是底层的“值代码”,另一种是上层的“类型代码”。前者使用 JavaScript 语法,后者使用 TypeScript 的类型语法。
它们是可以分离的,TypeScript 的编译过程,实际上就是把“类型代码”全部拿掉,只保留“值代码”。
编写 TypeScript 项目时,不要混淆哪些是值代码,哪些是类型代码。
Typescript 的基础类型
| 数据类型 | 关键字 |
|---|---|
| 布尔类型 | boolean |
| 字符串类型 | string |
| 数字类型 | number |
| bigint 类型 | bigint |
| symbol 类型 | symbol |
| 对象类型 | object |
| undefined 类型 | undefined |
| null 类型 | null |
TypeScript 继承了 JavaScript 的类型设计,以上8种类型可以看作 TypeScript 的基本类型。
注意,上面所有类型的名称都是小写字母,首字母大写的Number、String、Boolean等在 JavaScript 语言中都是内置对象,而不是类型名称。
另外,undefined 和 null 既可以作为值,也可以作为类型,取决于在哪里使用它们。
这8种基本类型是 TypeScript 类型系统的基础,复杂类型由它们组合而成。
any 类型
any 类型表示没有任何限制,该类型的变量可以赋予任意类型的值。
变量类型一旦设为any,TypeScript 实际上会关闭这个变量的类型检查。即使有明显的类型错误,只要句法正确,都不会报错。
let x:any = 'hello';
x(1) // 不报错
x.foo = 100; // 不报错
上面示例中,变量x的值是一个字符串,但是把它当作函数调用,或者当作对象读取任意属性,TypeScript 编译时都不报错。原因就是x的类型是any,TypeScript 不对其进行类型检查。
由于这个原因,应该尽量避免使用any类型,否则就失去了使用 TypeScript 的意义。
回到上面说的那个问题,当我这样写的时候,为什么没报错。
let a
console.log(a)
- 使用
let或const声明变量,但不指定初始值。此时,变量会被默认初始化为undefined,并且其类型会被推断为any,除非在严格模式下启用了更严格的类型检查。
实际开发中,any类型主要适用以下两个场合。
(1)出于特殊原因,需要关闭某些变量的类型检查,就可以把该变量的类型设为any。
(2)为了适配以前老的 JavaScript 项目,让代码快速迁移到 TypeScript,可以把变量类型设为any。有些年代很久的大型 JavaScript 项目,尤其是别人的代码,很难为每一行适配正确的类型,这时你为那些类型复杂的变量加上any,TypeScript 编译时就不会报错。
总之,TypeScript 认为,只要开发者使用了any类型,就表示开发者想要自己来处理这些代码,所以就不对any类型进行任何限制,怎么使用都可以。
从集合论的角度看,any类型可以看成是所有其他类型的全集,包含了一切可能的类型。TypeScript 将这种类型称为“顶层类型”(top type),意为涵盖了所有下层。
有关any类型,还有一些要注意的点,以及对于类型还需要注意的小知识,我们放到第二节细🔒。请持续关注。
。。。未完待续