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 相关文章推荐
JavaScript 设计模式学习 Factory
Jul 29 Javascript
javascript中encodeURI和decodeURI方法使用介绍
May 06 Javascript
IE6下javasc#ipt:void(0) 无效的解决方法
Dec 23 Javascript
JS阻止冒泡事件以及默认事件发生的简单方法
Jan 17 Javascript
jQuery Validate表单验证入门学习
Dec 18 Javascript
功能强大的Bootstrap效果展示(二)
Aug 03 Javascript
Js查找字符串中出现次数最多的字符及个数实例解析
Sep 05 Javascript
js控制按钮,防止频繁点击响应的实例
Feb 15 Javascript
原生javascript上传图片带进度条【实例分享】
Apr 06 Javascript
jquery 给动态生成的标签绑定事件的几种方法总结
Feb 24 jQuery
利用Vue构造器创建Form组件的通用解决方法
Dec 03 Javascript
Vue 禁用浏览器的前进后退操作
Sep 04 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(2)
2006/10/09 PHP
php学习之运算符相关概念
2011/06/09 PHP
ThinkPHP删除栏目(实现批量删除栏目)
2017/06/21 PHP
一个对于js this关键字的问题
2007/01/09 Javascript
用JavaScript隐藏控件的方法
2009/09/21 Javascript
JavaScript中实现块作用域的方法
2010/04/01 Javascript
javascript动态加载实现方法一
2012/08/22 Javascript
javascript之Partial Application学习
2013/01/10 Javascript
有关于eclipse配置spket需要注意的一些地方
2013/04/07 Javascript
javascript ajax 仿百度分页函数
2013/10/29 Javascript
jquery解析XML字符串和XML文件的方法说明
2014/02/21 Javascript
详解JavaScript对象序列化
2016/01/19 Javascript
原生js实现返回顶部缓冲效果
2017/01/18 Javascript
js控制一个按钮是否可点击(可使用)disabled的实例
2017/02/14 Javascript
Android中Okhttp3实现上传多张图片同时传递参数
2017/02/18 Javascript
AngularJS实现的2048小游戏功能【附源码下载】
2018/01/03 Javascript
vue slot与传参实例代码讲解
2019/04/28 Javascript
微信小程序获取用户信息并保存登录状态详解
2019/05/10 Javascript
Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条
2019/06/24 Javascript
JSONP 的原理、理解 与 实例分析
2020/05/16 Javascript
jQuery 淡入/淡出效果函数用法分析
2020/05/19 jQuery
vue+element-ui JYAdmin后台管理系统模板解析
2020/07/28 Javascript
[03:28]2014DOTA2国际邀请赛 走近EG战队天才中单Arteezy
2014/07/12 DOTA
Python urllib模块urlopen()与urlretrieve()详解
2013/11/01 Python
Python中title()方法的使用简介
2015/05/20 Python
Python代码解决RenderView窗口not found问题
2016/08/28 Python
Django 后台获取文件列表 InMemoryUploadedFile的例子
2019/08/07 Python
python 输出列表元素实例(以空格/逗号为分隔符)
2019/12/25 Python
双立人美国官方商店:ZWILLING集团餐具和炊具
2020/05/07 全球购物
简述你对Statement,PreparedStatement,CallableStatement的理解
2013/03/25 面试题
《夕阳真美》教学反思
2014/04/27 职场文书
乐观自信演讲稿范文
2014/05/21 职场文书
工会优秀工作者事迹
2014/08/17 职场文书
大学生见习报告总结
2014/11/04 职场文书
Pytorch中TensorBoard及torchsummary的使用详解
2021/05/12 Python
使用python+pygame开发消消乐游戏附完整源码
2021/06/10 Python