学习TypeScript的背景
都2023年了,你如果还不会TS,都不好意思说自己是个前端,为什么会有这种说法?随着前端流行框架的源码都使用TS重构,TS成为了前端开发的香饽饽。TS最大的好处就是在开发阶段就能将一些错误暴露,不至于像JS一样等上线了才会发现一些不可预知的问题。TS适合在复杂的大型项目中使用,便于维护,而对于一些中小型项目,使用JS就足够了,毕竟使用TS也是有一定成本的。
any
-
基本含义:关闭TS的类型检查,所以在使用any类型时尽量少用,能不用则不用,否则相当于在写JS,就失去了写TS的意义。当然,TS团队既然设计了any这个类型,存在肯定有它的价值,对于某些场景,我们不希望TS进行类型检验或者说类型校验意义不大,这时候就可以使用any类型,避免定义一些繁杂且意义不大的类型。
-
类型推断问题
function add(x, y) {
return x + y
}
add(1, [2,3])
比如上面这段代码,x和y没有定义类型,TS推断为any类型,导致调用的时候传什么都不会报错,但相加肯定是不对的。对于这个问题,TS提供了一个编译选项noImplicitAny,在tsconfig.json的compilerOptions对象中将此选项配置为true,这样推断出any类型就会报错。
- 污染其他变量的问题
let x:any = 'zs'
let y:number
y = x
y = y * 10
因为x为any类型,any类型可以赋值给number,不会报错,注意如果将y定义成never类型,就会报错,因为any不可以赋值给never类型。这时候就会变成一个字符串乘以数字,显然是不对的,但是TS也检查不出错误,问题只有在运行时才会暴露。
unknown
为了解决any污染变量的问题,TS引入了unknown类型,表示类型不确定。定义的时候不确定,使用的时候需要做类型收窄,也就是确定某一种类型,当我们想使用any类型时,不妨先定义成unknown类型,unknown也被称为严格版的any,严格体现在以下几点:
- unknown类型的变量,不能直接赋值给其他类型的变量(除了any、unknown)
let a:unknown = 1
let b:boolean = a // 报错 避免污染问题
- 不能直接调用unknown类型变量的方法和属性
let a:unknown = { name: 'zs' }
a.name // 报错
- 能使用的运算符有限:
只能进行比较运算(运算符
==、===、!=、!==、||、&&、?)、取反运算(运算符!)、typeof运算符和instanceof运算符这几种,其他运算都会报错。 - 使用unknown类型变量
let a:unknown = 1
if (typeof a === 'number') {
let b = a + 1 // 正确
}
never
- 基本含义:表示那些永远不会发生的值的类型,相当于集合中的空集,不可能赋给它任何值,否则都会报错。
- 用法
- 函数抛错
function throwError(message: string): never {
throw new Error(message);
}
- 用于表示某些条件下不可能发生的分支
function checkNever(x: string | number): never {
throw new Error('Unexpected value: ' + x);
}
function example(value: string | number) {
if (typeof value === "string") {
// 在这里,TypeScript 推断出 value 的类型为 string
console.log(value.toUpperCase());
} else if (typeof value === 'number') {
// 在这里,TypeScript 推断出 value 的类型为 number
console.log(value);
} else {
// 在这里,TypeScript 推断出 value 的类型为 never
checkNever(value);
}
}
- 不会结束的循环
function infiniteLoop(): never {
while (true) {
console.log('This is an infinite loop.');
}
}
参考:
阮一峰TypeScript教程