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,超强推荐share.js
Dec 23 Javascript
jquery.qrcode在线生成二维码使用示例
Aug 21 Javascript
JavaScript中创建字典对象(dictionary)实例
Mar 31 Javascript
再谈javascript常见错误及解决方法
Sep 16 Javascript
Angularjs中controller的三种写法分享
Sep 21 Javascript
JS实现评价的星星功能
Aug 20 Javascript
vue+webpack 打包文件 404 页面空白的解决方法
Feb 28 Javascript
webpack-url-loader 解决项目中图片打包路径问题
Feb 15 Javascript
详解vue中使用微信jssdk
Apr 19 Javascript
vue实现分环境打包步骤(给不同的环境配置相对应的打包命令)
Jun 04 Javascript
如何使用proxy实现一个简单完整的MVVM库的示例代码
Sep 17 Javascript
JavaScript实现放大镜效果代码示例
Apr 29 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
异世界新番又来了,同样是从零开始,男主的年龄降到5岁
2020/04/09 日漫
PHP在特殊字符前加斜杠的实现代码
2011/07/17 PHP
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
2013/01/11 PHP
PHP中如何调用webservice的实例参考
2013/04/25 PHP
自己写的兼容低于PHP 5.5版本的array_column()函数
2014/10/24 PHP
Smarty中调用FCKeditor的方法
2014/10/27 PHP
PHP基于CURL进行POST数据上传实例
2014/11/10 PHP
PHP中imagick函数的中文解释
2015/01/21 PHP
php之static静态属性与静态方法实例分析
2015/07/30 PHP
Laravel 数据库加密及数据库表前缀配置方法
2019/10/10 PHP
jquery 事件执行检测代码
2009/12/09 Javascript
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
jquery中使用$(#form).submit()重写提交表单无效原因分析及解决
2013/03/25 Javascript
js弹出层包含flash 不能关闭隐藏的2种处理方法
2013/06/17 Javascript
IE中图片的onload事件无效问题和解决方法
2014/06/06 Javascript
易被忽视的js事件问题总结
2016/05/14 Javascript
elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo
2019/07/03 Javascript
JavaScript复制变量三种方法实例详解
2020/01/09 Javascript
JavaScript实现多个物体同时运动
2020/03/12 Javascript
Angular8 简单表单验证的实现示例
2020/06/03 Javascript
解决vue-router路由拦截造成死循环问题
2020/08/05 Javascript
微信小程序以7天为周期连续签到7天功能效果的示例代码
2020/08/20 Javascript
解决vue请求接口第一次成功,第二次失败问题
2020/09/08 Javascript
使用python绘制人人网好友关系图示例
2014/04/01 Python
python基础教程之基本数据类型和变量声明介绍
2014/08/29 Python
numpy.random.seed()的使用实例解析
2018/02/03 Python
python selenium自动上传有赞单号的操作方法
2018/07/05 Python
Python实现快速傅里叶变换的方法(FFT)
2018/07/21 Python
python利用百度云接口实现车牌识别的示例
2020/02/21 Python
简述Html5 IphoneX 适配方法
2018/02/08 HTML / CSS
加拿大奢华时装品牌:Mackage
2018/01/10 全球购物
教师敬业奉献模范事迹材料
2014/05/18 职场文书
2014年个人教学工作总结
2014/12/09 职场文书
2015年世界环境日活动总结
2015/02/11 职场文书
win10更新失败无限重启解决方法
2022/04/19 数码科技
python计算列表元素与乘积详情
2022/08/05 Python