TypeScript中never类型的妙用详解

 更新时间:2023年11月21日 10:52:28   作者:子辰Web草庐  
TypeScript 是一种静态类型的编程语言,它可以让我们在编写 JavaScript 代码时,提前发现并避免一些潜在的错误,本文主要为大家介绍了TypeScript中never类型的妙用,感兴趣的可以了解下

TypeScript 是一种静态类型的编程语言,它可以让我们在编写 JavaScript 代码时,提前发现并避免一些潜在的错误。

但是,有时候我们在修改类型时,可能会忘记修改一些相关的代码,导致类型不匹配或者缺少分支处理等问题。

有没有一种方法,可以让我们在修改类型时更加轻松和精确呢?

答案是肯定的!

我是渡一子辰老师,今天我来向你介绍一个重要的类型——never 类型。

它是 TypeScript 中最小的类型,它表示一个永远不会出现的值。

子辰还将告诉你如何利用 never 类型来确保类型约束的精确性,避免在类型修改过程中导致的错误。

什么是 never 类型

在 TypeScript 中,never 类型表示一个永远不会出现的值。

它是所有类型的子类型,也就是说,任何类型都可以赋值给 never 类型,但是 never 类型不能赋值给任何类型,当然除了它自己。

never 类型有什么用呢?我们可以用它来表示一些永远不会发生的情况,比如:

  • 抛出异常的函数
  • 死循环的函数
  • 永远不会进入的分支

例如:

// 抛出异常的函数
function error(message: string): never {
  throw new Error(message);
}

// 死循环的函数
function loop(): never {
  while (true) {}
}

// 永远不会进入的分支
function foo(x: string | number) {
  if (typeof x === "string") {
  // do something
  } else if (typeof x === "number") {
  // do something else
  } else {
  // x is never
  const n: never = x;
  }
}

在上面的例子中,error 函数和 loop 函数都永远不会返回任何值,所以它们的返回类型是 never 。

foo 函数中,如果 x 是 string 或者 number ,就会进入相应的分支处理;如果 x 不是这两种类型,就会进入最后一个分支,但是这个分支永远不会进入,因为 x 的类型已经被收缩为 never 了。

所以我们可以用 never 类型来标记这个分支,并且把 x 赋值给一个 never 类型的变量 n ,这样就可以确保这个分支永远不会被执行。

never 的妙用

我们已经知道了 never 类型可以表示一些永远不会发生的情况,那么我们如何利用它来确保类型约束的精确性呢?

我们来看一个例子。

假设我们要封装一个 Ajax 请求的方法。

// 定义一个类型
type Method = 'GET' | 'POST'
// 封装一个 Ajax 请求的方法,为两个参数约束类型
function request(method: Method, url: string) { }

可以看到方法已经写好了,并且在调用 request 时也有提示了。

那么我们再来写函数里边的东西。

type Method = 'GET' | 'POST'
function request(method: Method, url: string) {
  // 因为有多种请求类型,我们这里用 switch
  // 每一个类型随便给它返回一个值仅做模拟
  switch (method) {
    case "GET":
      return "get"
    case "POST":
      return "post"
    default:
      return 'default'
  }
}

可以看到函数里边用 switch 来根据不同的请求类型返回不同的值。

但是这里有一个问题:我们定义了 Method 类型只有两种可能:GET 和 POST ,那么为什么还要写 default 分支呢?因为这个分支永远不会进入!

我们看一下 default 分支里是什么类型。

可以看到,它变成了 never 类型,这就得益于 TS 里的类型收缩,就是 TS 他会分析你的分支,根据你分支的条件来对类型做一个相应的收缩。

比如在下图的分支里,就被收缩成了 GET 值,它就不在是联合类型了。

那么在 default 里由于这个分支永远不会进来,所以说它就用类型 never 来表示了。

那么这个对我们实际开发到底有什么用呢?

我们考虑这么一种情况,如果我们不写 default 分支,我们对 Method 类型扩展了其他可能性,比如:PUT 或者 DELETE 等。

你看,在下图中我们加了一个 PUT 类型以后,并没有报错,你压根就不知道这个函数里还应该加一个 PUT 分支。

当你的代码写多了,然后再非常繁杂的代码里边,改了一个类型,你就很难知道,你这个改动会影响到哪些地方。

就是其他地方的代码到底哪些地方会做相应的修改,你是很难知道的。

当然这个代码很少,一眼就能看出来,那如果是上万行代码呢?因为 TS 往往是在大型项目工程中使用的,几万行代码你还能清楚的知道吗?

这个时候呢,我们就可以借助 never 了,来看下怎么做。

type Method = 'GET' | 'POST'
function request(method: Method, url: string) {
  switch (method) {
    case "GET":
      return "get"
    case "POST":
      return "post"
    default:
      const n: never = method;
      return n
  }
}

我们回到最初的情况,我们就加一个 default 分支,分支里定一个变量 n,标注为 never 类型,然后吧 method 赋值给它,然后返回这个 n。

它不会影响代码的执行,因为这个分支永远进不来。

而且这个赋值也是安全的,因为现在 default 分支里的 method 是 never 类型,never 是可以赋值给 never 的,但是其他类型就不能赋值给 never 了。

接下来我们就可以放心大胆的去修改类型了。

当我们加了一个 PUT 以后,就会发现报错了,因为 TS 的类型收缩,它知道分支里还有一种情况,就是 PUT,那么这种类型是不能赋值给 never 的,于是这里就报错了。

这样子呢,你就非常清楚这个地方还需要去增加一个分支,要做相应的修改。

比如说有很多这个函数,根据报错,就能很清楚的知道哪些地方要做修改了。

这是 never 类型在 TS 里边非常常见的一种做法,这种做法在大型项目里边及其有用。

总结

本文主要就是帮助你理解 never 类型在 TypeScript 中的应用及其优势。

在 TypeScript 中,never 类型表示一个永远不会出现的值,它可以在类型收缩时进行自动推导,使代码更加稳定可靠。

在函数中,我们可以利用 never 类型来确保类型约束的精确性,避免了在类型修改过程中导致的错误。特别是在大型项目中,never 类型可以帮助我们更好地维护代码,减少因修改类型而导致代码修改和错误的风险。

例如,我们文章中的例子,通过分析代码分支,我们可以使用 never 类型来标记永远不会进入的分支。这样一来,我们在以对类型进行扩展时,就可以很快地知道在哪些地方需要进行相应的修改,从而提高代码的可维护性和稳定性。

在项目开发中,特别是大型项目开发中,掌握使用 never 类型的技巧,可以让同学们更加高效、精准地编写出高质量的代码。

以上就是TypeScript中never类型的妙用详解的详细内容,更多关于TypeScript never类型的资料请关注脚本之家其它相关文章!

相关文章

  • Three.js+React制作3D梦中海岛效果

    Three.js+React制作3D梦中海岛效果

    深居内陆的人们,大概每个人都有过大海之梦吧。本文使用React+Three.js技术栈,实现3D海洋和岛屿,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-05-05
  • JS实现的ajax和同源策略(实例讲解)

    JS实现的ajax和同源策略(实例讲解)

    下面小编就为大家分享一篇JS实现的ajax和同源策略的实例讲解,具有很好的参考价值,希望对大家有所帮助
    2017-12-12
  • js 字符串反转(倒序)的几种方式总结

    js 字符串反转(倒序)的几种方式总结

    这篇文章主要介绍了js 字符串反转(倒序)的几种方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • JS作用域链详解

    JS作用域链详解

    这篇文章主要为大家详细介绍了JS作用域链的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 原生JS获取URL链接参数的几种常见方法

    原生JS获取URL链接参数的几种常见方法

    这篇文章主要给大家介绍了关于利用原生JS获取URL链接参数的几种常见方法,文中通过实例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-03-03
  • js实现随机数字字母验证码

    js实现随机数字字母验证码

    这篇文章主要为大家详细介绍了js随机验证码的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 比较JavaScript对象的四种方式

    比较JavaScript对象的四种方式

    这篇文章主要介绍了比较 JavaScript 对象的四种方式,对js对象感兴趣的同学,可以参考下
    2021-04-04
  • js实现图片轮播效果学习笔记

    js实现图片轮播效果学习笔记

    这篇文章主要为大家详细介绍了js实现图片轮播效果的学习笔记,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • bootstrap fileinput 上传插件的基础使用

    bootstrap fileinput 上传插件的基础使用

    这篇文章主要介绍了bootstrap fileinput 上传插件基础使用,重点是把界面做得更加友好,更好的增加用户体验。对bootstrap fileinput知识感兴趣的朋友通过本文一起学习吧
    2017-02-02
  • bootstrap table单元格新增行并编辑

    bootstrap table单元格新增行并编辑

    这篇文章主要为大家详细介绍了bootstrap table单元格新增行并编辑的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05

最新评论