TypeScript_any、unknown、never类型

89 阅读3分钟

学习TypeScript的背景

都2023年了,你如果还不会TS,都不好意思说自己是个前端,为什么会有这种说法?随着前端流行框架的源码都使用TS重构,TS成为了前端开发的香饽饽。TS最大的好处就是在开发阶段就能将一些错误暴露,不至于像JS一样等上线了才会发现一些不可预知的问题。TS适合在复杂的大型项目中使用,便于维护,而对于一些中小型项目,使用JS就足够了,毕竟使用TS也是有一定成本的。

any

  1. 基本含义:关闭TS的类型检查,所以在使用any类型时尽量少用,能不用则不用,否则相当于在写JS,就失去了写TS的意义。当然,TS团队既然设计了any这个类型,存在肯定有它的价值,对于某些场景,我们不希望TS进行类型检验或者说类型校验意义不大,这时候就可以使用any类型,避免定义一些繁杂且意义不大的类型。

  2. 类型推断问题

function add(x, y) {
  return x + y
}
add(1, [2,3])

比如上面这段代码,x和y没有定义类型,TS推断为any类型,导致调用的时候传什么都不会报错,但相加肯定是不对的。对于这个问题,TS提供了一个编译选项noImplicitAny,在tsconfig.json的compilerOptions对象中将此选项配置为true,这样推断出any类型就会报错。

  1. 污染其他变量的问题
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,严格体现在以下几点:

  1. unknown类型的变量,不能直接赋值给其他类型的变量(除了any、unknown)
let a:unknown = 1
let b:boolean = a // 报错  避免污染问题
  1. 不能直接调用unknown类型变量的方法和属性
let a:unknown = { name: 'zs' }
a.name // 报错
  1. 能使用的运算符有限: 只能进行比较运算(运算符=====!=!==||&&?)、取反运算(运算符!)、typeof运算符和instanceof运算符这几种,其他运算都会报错。
  2. 使用unknown类型变量
let a:unknown = 1
if (typeof a === 'number') {
  let b = a + 1 // 正确
}

never

  1. 基本含义:表示那些永远不会发生的值的类型,相当于集合中的空集,不可能赋给它任何值,否则都会报错。
  2. 用法
  • 函数抛错
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教程