TypeScript 使用 Tuple Union 声明函数重载


Posted in Javascript onApril 07, 2022

问题:

TypeScript 中为函数添加多个签名后,依然需要添加相应的代码来判断并从不同的签名参数列表中获取对应的参数。过去常见的写法:

function refEventEmitter(event?: string): void;
function refEventEmitter(event: string, callback: () => void): void;
function refEventEmitter(callback: () => void): void;
function refEventEmitter(
  eventOrCallback?: string | (() => void),
  callback?: () => void,
): void {
  let event: string | undefined;

  if (typeof eventOrCallback === 'function') {
    callback = eventOrCallback;
  } else {
    event = eventOrCallback;
  }

  // ...
}

这个过程因为将原有参数列表直接按序号拍平,参数之间的类型关联需要人肉确保正确。

技巧:

这时我们可以通过使用tuple union 的参数类型,来无脑处理各种函数重载情况:

function refEventEmitter(event?: string): void;
function refEventEmitter(event: string, callback: () => void): void;
function refEventEmitter(callback: () => void): void;
function refEventEmitter(
  ...args:
    | [event?: string]
    | [
        event: string,
        callback: () => unknown,
      ]
    | [callback: () => unknown]
): void {
  let [event, callback] =
    args.length === 2
      ? args
      : typeof args[0] === 'function'
      ? [undefined, args[0]]
      : [args[0], undefined];

  // ...
}

实际上,此时上方的签名列表也不再需要了:

function refEventEmitter(
  ...args:
    | [event?: string]
    | [
        event: string,
        callback: () => unknown,
      ]
    | [callback: () => unknown]
): void {
  let [event, callback] =
    args.length === 2
      ? args
      : typeof args[0] === 'function'
      ? [undefined, args[0]]
      : [args[0], undefined];

  // ...
}
这篇其实拖了有点久,在写的时候发现 TypeScript 已经内置了 "Convert overload list to single signature" 的重构选项,可以一键将重载列表变为参数 tuple union。

不过到这里其实还存在问题,TypeScript 中 typeof 条件判断不能对整个对象进行收窄,只能收窄被 typeof 到的某个元素、属性。上面的例子中,如果需要的不只是 args[0] 就会出现问题。

此时我们可以引入一个工具函数 isTypeOfProperty(object, key, type)

此时实现就变成了:

function refEventEmitter(
  ...args:
    | [event?: string]
    | [
        event: string,
        callback: () => unknown,
      ]
    | [callback: () => unknown]
): void {
  let [event, callback] =
    args.length === 2
      ? args
      : isTypeOfProperty(args, 0, 'function')
      ? [undefined, args[0]]
      : [args[0], undefined];

  // ...
}

到此这篇关于TypeScript 使用 Tuple Union 声明函数重载的文章就介绍到这了,更多相关TypeScript 声明函数重载内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js判断字符是否是汉字的两种方法小结
Jan 03 Javascript
js图片轮播特效代码分享
Sep 07 Javascript
javascript结合Flexbox简单实现滑动拼图游戏
Feb 18 Javascript
JQuery 的跨域方法推荐_可跨任何网站
May 18 Javascript
jquery使用on绑定a标签无效 只能用live解决
Jun 02 Javascript
Js查找字符串中出现次数最多的字符及个数实例解析
Sep 05 Javascript
纯js三维数组实现三级联动效果
Feb 07 Javascript
angular2中Http请求原理与用法详解
Jan 11 Javascript
vue.js 微信支付前端代码分享
Feb 10 Javascript
Vue EventBus自定义组件事件传递
Jun 25 Javascript
基于node+vue实现简单的WebSocket聊天功能
Feb 01 Javascript
react+antd 递归实现树状目录操作
Nov 02 Javascript
Axios代理配置及封装响应拦截处理方式
vue-cil之axios的二次封装与proxy反向代理使用说明
Apr 07 #Vue.js
动态规划之使用备忘录来改进Javascript函数
Apr 07 #Javascript
vue实现拖拽交换位置
Apr 07 #Vue.js
使用Ajax实现进度条的绘制
Vue.Draggable实现交换位置
vue-cli3.0修改打包后的文件名和文件地址,打包后本地运行报错解决
You might like
基于PHP文件操作的详解
2013/06/05 PHP
Mac环境下php操作mysql数据库的方法分享
2015/05/11 PHP
thinkPHP商城公告功能开发问题分析
2016/12/01 PHP
详解laravel passport OAuth2.0的4种模式
2019/11/04 PHP
几个常用的JavaScript字符串处理函数 - split()、join()、substring()和indexOf()
2009/06/02 Javascript
JS弹出层的显示与隐藏示例代码
2013/12/27 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
2014/05/08 Javascript
jquery实现简单的banner轮播效果【实例】
2016/03/30 Javascript
canvas压缩图片转换成base64格式输出文件流
2017/03/09 Javascript
vue.js单页面应用实例的简单实现
2017/04/10 Javascript
Node.js服务器开启Gzip压缩教程
2017/08/11 Javascript
详解Angular结合zTree异步加载节点数据
2018/01/20 Javascript
vue keep-alive请求数据的方法示例
2018/05/16 Javascript
vue中使用props传值的方法
2019/05/08 Javascript
使用webpack搭建pixi.js开发环境
2020/02/12 Javascript
JavaScript设计模式---单例模式详解【四种基本形式】
2020/05/16 Javascript
解决vue项目获取dom元素宽高总是不准确问题
2020/07/29 Javascript
Python实现对比不同字体中的同一字符的显示效果
2015/04/23 Python
python、java等哪一门编程语言适合人工智能?
2017/11/13 Python
python基于http下载视频或音频
2018/06/20 Python
python实现flappy bird小游戏
2018/12/24 Python
详解Python 调用C# dll库最简方法
2019/06/20 Python
对Python函数设计规范详解
2019/07/19 Python
Python3实现二叉树的最大深度
2019/09/30 Python
Python笔记之工厂模式
2019/11/20 Python
python 解决Windows平台上路径有空格的问题
2020/11/10 Python
一款纯css3实现的竖形二级导航的实例教程
2014/12/11 HTML / CSS
HTML实现代码雨源码及效果示例
2020/02/25 HTML / CSS
什么时候用assert
2015/05/08 面试题
优秀学生党员先进事迹材料
2014/05/29 职场文书
整顿机关作风心得体会
2014/09/10 职场文书
大学运动会加油稿200字(5篇)
2014/09/27 职场文书
电工生产实习心得体会
2016/01/22 职场文书
python 破解加密zip文件的密码
2021/04/22 Python
Python&Matlab实现樱花的绘制
2022/04/07 Python
Golang 遍历二叉树
2022/04/19 Golang