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实例教程(19) 使用HoTMetal(1)
Dec 23 Javascript
对于this和$(this)的个人理解
Sep 08 Javascript
前台js调用后台方法示例
Dec 02 Javascript
jQuery使用$.ajax进行即时验证实例详解
Dec 11 Javascript
JavaScript+html5 canvas实现图片破碎重组动画特效
Feb 22 Javascript
JS中多种方式创建对象详解
Mar 22 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
Sep 26 Javascript
loading动画特效小结
Jan 22 Javascript
利用nvm管理多个版本的node.js与npm详解
Nov 02 Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
Apr 16 Javascript
vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
Jul 17 Javascript
详解微信小程序入门从这里出发(登录注册、开发工具、文件及结构介绍)
Jul 21 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采集时被封ip的解决方法
2010/08/29 PHP
PHP mb_convert_encoding文字编码的转换函数介绍
2011/11/10 PHP
Smarty中的注释和截断功能介绍
2015/04/09 PHP
浅析PHP中的i++与++i的区别及效率
2016/06/15 PHP
基于Web标准的UI组件 — 树状菜单(2)
2006/09/18 Javascript
ajax 缓存 问题 requestheader
2010/08/01 Javascript
JavaScript高级程序设计(第3版)学习笔记7 js函数(上)
2012/10/11 Javascript
jQuery实现div浮动层跟随页面滚动效果
2014/02/11 Javascript
JS实现控制表格行文本对齐的方法
2015/03/30 Javascript
jQuery表单事件实例代码分享
2016/08/18 Javascript
基于Javascript实现文件实时加载进度的方法
2016/10/12 Javascript
JS函数修改html的元素内容,及修改属性内容的方法
2016/10/28 Javascript
Bootstrap CSS组件之下拉菜单(dropdown)
2016/12/17 Javascript
微信小程序手势操作之单触摸点与多触摸点
2017/03/10 Javascript
JS实现问卷星自动填问卷脚本并在两秒自动提交功能
2020/06/17 Javascript
通过js实现压缩图片上传功能
2020/02/25 Javascript
Vue如何基于vue-i18n实现多国语言兼容
2020/07/17 Javascript
vue中axios封装使用的完整教程
2021/03/03 Vue.js
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
Python实现的弹球小游戏示例
2017/08/01 Python
python实现银联支付和支付宝支付接入
2019/05/07 Python
一篇文章弄懂Python中所有数组数据类型
2019/06/23 Python
python实现堆排序的实例讲解
2020/02/21 Python
django模型动态修改参数,增加 filter 字段的方式
2020/03/16 Python
python中的django是做什么的
2020/07/31 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
2020/08/07 Python
python 进程池pool使用详解
2020/10/15 Python
CSS3弹性伸缩布局之box布局
2016/07/12 HTML / CSS
SEPHORA丝芙兰德国官方购物网站:化妆品、护肤品和香水
2020/01/21 全球购物
写clone()方法时,通常都有一行代码,是什么?
2012/10/31 面试题
公积金转移接收函
2014/01/11 职场文书
购房委托书范本
2014/09/18 职场文书
2015大学生暑假调查报告
2015/07/13 职场文书
python基础学习之生成器与文件系统知识总结
2021/05/25 Python
关于JS中的作用域中的问题思考分享
2022/04/06 Javascript
windows10声卡驱动怎么安装?win10声卡驱动安装操作步骤教程
2022/08/05 数码科技