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本身的局限性 别让javascript做太多事
Mar 23 Javascript
关于js获取radio和select的属性并控制的代码
May 12 Javascript
JavaScript中json对象和string对象之间相互转化
Dec 26 Javascript
javascript回车完美实现tab切换功能
Mar 13 Javascript
提交按钮的name='submit'引起的js失效问题及原因
Feb 25 Javascript
JavaScript控制按钮可用或不可用的方法
Apr 03 Javascript
jQuery监控文本框事件并作相应处理的方法
Apr 16 Javascript
vue.js选中动态绑定的radio的指定项
Jun 02 Javascript
js实现Tab选项卡切换效果
Jul 17 Javascript
angular 实时监听input框value值的变化触发函数方法
Aug 31 Javascript
JS实现可针对算术表达式求值的计算器功能示例
Sep 04 Javascript
Vue实现可移动水平时间轴
Jun 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
收音机怀古---春雷3P7图片欣赏
2021/03/02 无线电
咖啡界又出新概念,无需咖啡豆的分子咖啡
2021/03/03 咖啡文化
php 删除cookie和浏览器重定向
2009/03/16 PHP
CodeIgniter钩子用法实例详解
2016/01/20 PHP
javascript 强制刷新页面的实现代码
2009/12/13 Javascript
jQueryUI的Dialog的简单封装
2010/06/07 Javascript
JavaScript回调(callback)函数概念自我理解及示例
2013/07/04 Javascript
JavaScript中window、doucment、body的解释
2013/08/14 Javascript
JS测试显示屏分辨率以及屏幕尺寸的方法
2013/11/22 Javascript
jQuery调用RESTful WCF示例代码(GET方法/POST方法)
2014/01/26 Javascript
JS+CSS实现下拉列表框美化效果(3款)
2015/08/15 Javascript
Javascript将数字转化成为货币格式字符串
2016/06/22 Javascript
利用JS提交表单的几种方法和验证(必看篇)
2016/09/17 Javascript
Angularjs中ng-repeat的简单实例
2017/08/25 Javascript
JavaScript原型式继承实现方法
2019/11/06 Javascript
小程序接入腾讯位置服务的详细流程
2020/03/03 Javascript
react基本安装与测试示例
2020/04/27 Javascript
将Emacs打造成强大的Python代码编辑工具
2015/11/20 Python
Python获取当前公网ip并自动断开宽带连接实例代码
2018/01/12 Python
Python实现多级目录压缩与解压文件的方法
2018/09/01 Python
python实现指定字符串补全空格、前面填充0的方法
2018/11/16 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
Python API 自动化实战详解(纯代码)
2019/06/11 Python
python的pygal模块绘制反正切函数图像方法
2019/07/16 Python
python 采用paramiko 远程执行命令及报错解决
2019/10/21 Python
python 写一个文件分发小程序
2020/12/05 Python
html5的新增的标签和废除的标签简要概述
2013/02/20 HTML / CSS
linux面试题参考答案(10)
2016/10/26 面试题
生物科学专业个人求职信范文
2013/12/05 职场文书
导游词开场白
2015/01/31 职场文书
2015年五一劳动节活动总结
2015/02/09 职场文书
辞职书格式样本
2015/02/26 职场文书
2015年外联部工作总结
2015/04/03 职场文书
纪检干部学习心得体会
2016/01/23 职场文书
导游词之新疆尼雅遗址
2019/10/16 职场文书
MySQL如何使用使用Xtrabackup进行备份和恢复
2021/06/21 MySQL