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类型的资料请关注脚本之家其它相关文章!

相关文章

  • Bootstrap整体框架之JavaScript插件架构

    Bootstrap整体框架之JavaScript插件架构

    这篇文章主要介绍了Bootstrap整体框架之JavaScript插件架构的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • TypeScript快速上手语法及结合vue3用法详解

    TypeScript快速上手语法及结合vue3用法详解

    TypeScript是一种由微软开发的自由开源的编程语言,主要提供了类型系统和对ES6的支持,下面这篇文章主要给大家介绍了关于TypeScript快速上手语法及结合vue3用法的相关资料,需要的朋友可以参考下
    2024-02-02
  • UniApp WebView页面中的请求跨域问题解决

    UniApp WebView页面中的请求跨域问题解决

    在使用UniApp开发中,通过WebView组件加载本地网页时,往往会遇到跨域问题,下面这篇文章主要介绍了UniApp WebView页面中的请求跨域问题解决的相关资料,需要的朋友可以参考下
    2024-10-10
  • js弹出窗口简单实现代码

    js弹出窗口简单实现代码

    这篇文章主要为大家详细介绍了js弹出窗口的简单实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • js正则表达式之前瞻后顾与非捕获分组

    js正则表达式之前瞻后顾与非捕获分组

    话说自从学前端以来听到过多次这样的"笑话",程序员分为会正则的和不会正则的,可见正则的重要性,这篇文章主要给大家介绍了关于js正则表达式之前瞻后顾与非捕获分组的相关资料,需要的朋友可以参考下
    2021-10-10
  • vue路由权限校验功能的实现代码

    vue路由权限校验功能的实现代码

    这篇文章主要介绍了vue路由权限校验功能的实现代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • javascript实现考勤日历功能

    javascript实现考勤日历功能

    这篇文章主要为大家详细介绍了javascript实现考勤日历功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • get  post jsonp三种数据交互形式实例详解

    get post jsonp三种数据交互形式实例详解

    本文通过实例给大家详细介绍了get post jsonp三种数据交互形式,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-08-08
  • echarts折线图实现部分虚线部分实线效果的方法

    echarts折线图实现部分虚线部分实线效果的方法

    在折线图中,通常实线表示实际数据,而虚线用于表示预测数据,这篇文章主要介绍了echarts折线图实现部分虚线部分实线效果的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-09-09
  • JS简单获取当前日期和农历日期的方法

    JS简单获取当前日期和农历日期的方法

    这篇文章主要介绍了JS简单获取当前日期和农历日期的方法,涉及javascript日期运算与字符串转换相关操作技巧,需要的朋友可以参考下
    2017-04-04

最新评论