这是我的第一篇博客,一起参与掘金新人创作活动,开启写作之路。
前言
快年底了,回顾一年,感觉啥也没做,心中不免焦虑起来。在掘金也是一篇文章也没发表过,正好近期要做 TypeScript 的相关分享,值此之际,我也想系统的学习和记录 TypeScript 的相关知识。
焦虑就是自由的“眩晕”。 ——《存在主义咖啡馆》
背景知识
JavaScript 语言的流行度有目共睹,但是伴随而来的问题也很多,包括全局变量、弱类型校验容易出错等等。于是就有了后来人想要改进这个语言,如下:
JavaScript 中的糟粕的比重超出了预料。 ——《JavaScript语言精粹》
- CoffeeScript:2009 年,受 ruby/python 启发,相当于简化版 JavaScript。自 ES6 以来开始不温不火。
- Dart: 2011 年,谷歌,设计者还是V8引擎的作者。代表框架 Flutter。
- TypeScript:2013 年,微软,作者海哥,支持强类型,是 JavaScript 的一个超集。社区活跃,拥抱 ES5/ES6 规范。
从上面比较中,TypeScript 算是目前这几个中最受欢迎的语言,加上 VS Code 全面加持,使用起来就更加方便了。
- 编辑器会提醒我们的变量的类型:
- 编辑器还会提示接口里面的属性
- TypeScript更像后端Java、C#这样的面向对象语言可以让JS开发大型企业应用
- 越来越多的项目是基于TS的,比如VSCode、Angular6、Vue3、React16
- TS提供的类型系统可以帮助我们在写代码的时候提供更丰富的语法提示
- 在创建前的编译阶段经过类型系统的检查,就可以避免很多线上的错误
类型注解
在 TypeScript 中,我们可以使用类型注解来标识类型,语法如下:
const 变量:类型 = 变量值;
const name:string = 'davont';
复制代码
TypeScript 的注解不是必须的,有时候编辑器会自动推算出表达式的类型,这叫做类型推断。
let name = 'davont'; // TypeScript 自动推算出是 string 类型
name = 777; // TypeScript 报错
复制代码
类型检查
类型检查时验证程序中类型约束是否正确的过程。类型检查分为两种:
- 静态类型检查:在程序编译时进行检查。TypeSCript 独有优势。静态检查也分两种:非严格类型检查,严格类型检查。
- 动态类型检查:在程序运行时进行检查。TypeScript 和 JavaScript 都支持。
非严格类型检查
非严格类型检查模式时默认模式,在该模式下,类型检查的规则相对宽松一些。不会对 null
和 undefined
值做过多限制。适合 JavaScript 迁移到 TypeScript 中使用。
严格类型检查
严格模式下,TypeScript 会尽可能地发现错误。建议在新的工程中启用严格类型检查。 在 tsconfig.json 里设置启动:
{
"compolerOptions":{
"strict":true,
}
}
复制代码
原始类型
JavaScript 语言中的每种原始类型都有其与之对应的 TypeScript 类型。但 TypeScript 自己还设计了其他扩展类型。
原始类型:
- boolean
- string
- number
- undefined
- null
- symbol
- bigint
- void
当然,还有其他类型,诸如枚举类型、子面量类型、顶端类型、尾端类型、数组类型、元组、对象类型、函数类型、接口、类、泛型等等。后面都会一一介绍。
boolean
对应 JavaScript 的 Boolean 原始类型。表示两个逻辑值: true 和 false。
const isShowTip:boolean = false;
复制代码
string
const tips:string = 'error';
const name:string = `${firstName} ${lastName}`;
复制代码
number
const bin:number = 0b1011;
const hex:number = 0xffff;
复制代码
undefined
undefined 类型只包含一个可能值,就是 undefined.
const myTips:undefined = undefined;
复制代码
null
同 undefined
,实际上 undefined
和 null
在 TypeScript 统称为 Nullable
。
const dom:null = null;
复制代码
symbol
TypeSctipt 中的 symbol 类型对应于 JavaScript 中的 Symbol 原始类型。该类型表示任意的 Symbol 值。
const sym1:symbol = Symbol('key');
const sym2:symbol = Symbol('key');
Symbol('key') === Symbol('key') // false
复制代码
bigint
bigint 对应 JavaScript中的 BigInt 原始类型。它只能表示整数,使用 BigInt 可以安全地存储和操作大整数。
const bin:bigint = 0b1010n;
const integer:bigint = 10n;
复制代码
void
void 类型用作函数的返回值类型。如果一个函数没有返回值,那么该函数的返回值就是 void 类型。
null 和 undefined 可以
function printName(name:string):void{
console.log(name);
}
复制代码
--strictNullChecks
TypeScript 增加了一种新的编译选项 --strictNullChecks
, 即严格的 null 检查模式。它主要约束于 undefined
和 null
。
试想下面一种场景:
function showNameLen(name:string):void {
console.log(name.length)
}
showNameLen(undefined);
复制代码
在将 strictNullChecks
设置成 false
的时候,事实上这段代码在编译时候不会报错,但是在运行时候会产生错误,因为在尝试读取 undefined
的 length
时候会产生类型错误。
这个问题可以通过设置 --strictNullChecks
编译选项来解决。
never
由于引入了 --strictNullChecks
,在这一模式下,null 和 undefined 能被检测到。所以 TypeScript 需要一种新的尾端类型( bottom type )。所以就引入了 never。 什么叫尾端类型?在类型系统里,尾端类型(bottom type)是所有其他类型的子类型。由于一个值不可能同时属于所有类型,例如一个值不能同时为数字类型和字符串类型,因此尾端类型中,不包含任何值。
尾端类型也被称为 0 类型或者空类型。
// Compiled with --strictNullChecks
function fn(x: number | string) {
if (typeof x === 'number') {
// x: number 类型
} else if (typeof x === 'string') {
// x: string 类型
} else {
cosnt check:never = x;
// x: never 类型
}
}
复制代码
上面代码中,如果有一天,x
的类型多了一个其他的单元类型,那么这段代码就会报错。有了 nerver 类型,它可以让你写出更加安全的代码。
Tips: never 类型介绍 :观看视频
any
any 是 TypeScript 的一种顶端类型,目前 TypeScript 的顶端类型只有 any
和 unknown
。
any 是所有类型的父类型,可以将任何类型的值都赋值给其他类型。
let a: any;
a = 777;
a = 'hello world';
a = [];
...
复制代码
同时,TypeScript允许将 any 类型赋值给其他类型。
let a: any;
let b: string = a;
let c: number = a;
复制代码
any 相当于 TypeScript 的最后一道防线,除非万不得已,最后不好用,不然TypeScript 就会变成 AnyScript(逃。
如何避免滥用 any ? 在 tsconfig.json
里,可以通过设置 --noImplicitAny
这个编译选项来控制。当启用了该编译选项时,如果发生了隐式的 any 类型转换,那么会产生编译错误。
{
"compilerOptions":{
"noImplicitAny": true
}
}
复制代码
unknown
TypeScript 顶端类型还有另外一种:unknown。
let x: unknown;
复制代码
和 any
一样,任何其他类型都可以赋值给 unknown
类型。
let k:unknow;
k = false;
k = 'hello world';
k = [];
复制代码
但是,unknown 类型是比 any 类型更安全的顶端类型,因为 unknown 类型只允许赋值给 any 类型和 unknown 类型,而不允许赋值给任何其他类型,该行为与 any 类型是不同的。
let k:unknown;
// 正确
const a1: any = k;
const a2: unknown = k;
// 错误
const a2:boolean = k;
const b2:string = k;
复制代码
同时,在 unknown 类型里也有其他的限制:
let k: unknown;
// 错误
k + 1;
x.foo;
x();
复制代码
any、unknown、void、never 区别
图片引用地址:传送门
any 和 unknown 很类似,但是 unknown 是在 TypeScript 3.0 才出,比 any 更加安全,unknown 不允许被赋值除 any 和 unknown 以外的变量类型,也不允许使用 unknown 类型的方法或属性。
never 类型和 void 类型都是用在函数上。never 是 永不返回|永不存在 的值的类型。意思就是这个函数压根就走不到返回类型的那一行。比如报错,比如死循环,比如条件语句等等。而 void 比较宽泛,它是没有返回值或者返回undefined、null。