一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
我们在学习和使用TS时,经常遇见any、unknown、never、void,如果不深入理解其意,就会感觉它们好像都是一样的,但又不一样,不知道怎么用,应该使用哪个。
any
任意类型。
任何值都可以赋值给any定义的变量。
可以赋值给任何类型的变量,除过never类型
不知道数据的类型的时候可以用到any类型,对any类型的后续操作,TS编译器不会管它,你可以在这个变量上调用任何方法(编辑器不会提示任何方法),如果any赋值给的是string类型数据,它也可以赋值给number类型变量, 但是后续操作这个number类型数据如果不注意可能会出错,因为编译器不管any类型数据,不会提示任何问题
let name: any = []; // 数组都可以赋值给any
name.split('_'); // 编译阶段不会报错,但明显是有问题的。
let tel: number = name; // 可以将any类型赋值给number类型
tel.toFixed(1); // 编译阶段不会报错,但明显也是有问题的
不建议使用any类型,能不用就不用,因为使用了any类型后续使用时可能会出现不可意料的问题。那什么时候可以用能,一般是只是定义该类型,使用的时候返回类型,后续不怎么用它即用及销毁,只是利用它的特性, 比如定义一些类型或则匹配类型时,如TS中的内置工具中有些就是用了any, 它只是做类型匹配用,因为它可以表示任何类型,并不使用,只是利用。
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
unknown
未知类型。
任何值都可以赋值给unknown定义的变量。
部分赋值给任何其他类型的变量。
和any有一点一样,在不知道数据的类型的使用可以用unknown,但是后续使用unknown的时候,不能调用任意方法也不能赋值给其它类型,因为TS编译器不知道它的类型,它和any不一样的一点是编译器会管这个类型。因此我们要使用unknown类型,必须让编译器知道,一般使用的时候要做类型断言或者类型守卫。
const person: any = { name: '小明' };
let name: unknown = person.name;
// 类型断言
let nameLength: number = (name as string).length;
// 类型守卫
if (typeof name === 'string') {
nameLength = name.length;
}
在使用any和unknown时首先想到使用unknown。
void
无任何类型。
只能被赋予null和undefined。"strictNullChecks": true模式下不能赋值null。
只能赋值给any、unknown和void类型变量。
和any相反,不能赋值给其他类型也不能赋予其他类型的值,所以一般没有地方用,常用于表示没有返回值的函数中,好像也没有其他地方能用。
function getName(): void {
console.log('没有返回值')
}
never
永不存在的值的类型, 它是任何类型的子类型。
不能被赋予任何类型值,"strictNullChecks": true模式下never不能赋值给never类型。
它可以赋值给任意类型。
什么是永不存在的类型,我们知道变量都有类型,那为什么要存在这个类型,它存在的意义就是为了一些特殊场景,没法用已有的类型表示,如函数中抛出异常函数无法运行完成,或者是函数中有个无限循环的无法终止函数这些函数的返回值就可以用never表示。还有就是可以在类型定义中使用,如条件类型判断中可以用never去除一些类型。
function getName(): never {
throw new Error("获取不到内容");
}
type NonNullable<T> = T extends null | undefined ? never : T;