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:void(0)的真正含义实例分析
Aug 20 Javascript
jQuery遍历Form示例代码
Sep 03 Javascript
Js实现网页键盘控制翻页的方法
Oct 30 Javascript
浅析javascript函数表达式
Feb 10 Javascript
老生常谈 js中this的指向
Jun 30 Javascript
使用BootStrap实现用户登录界面UI
Aug 10 Javascript
微信小程序 wxapp内容组件 progress详细介绍
Oct 31 Javascript
jquery 实时监听输入框值变化的完美方法(必看)
Jan 26 Javascript
vue-router beforeEach跳转路由验证用户登录状态
Dec 26 Javascript
JS手写一个自定义Promise操作示例
Mar 16 Javascript
详解如何修改 node_modules 里的文件
May 22 Javascript
Angular进行简单单元测试的实现方法实例
Aug 16 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实现ping
2006/10/09 PHP
一个自定义位数的php多用户计数器代码
2007/03/11 PHP
PHP实现的封装验证码类详解
2013/06/18 PHP
php使用cookie实现记住登录状态
2015/04/27 PHP
PHP中empty和isset对于参数结构的判断及empty()和isset()的区别
2015/11/15 PHP
PHP生成唯一ID之SnowFlake算法
2016/12/17 PHP
jQuery右键菜单contextMenu使用实例
2011/09/28 Javascript
基于jQuery捕获超链接事件进行局部刷新代码
2012/05/10 Javascript
jQuery实现类似淘宝购物车全选状态示例
2013/06/26 Javascript
JQUERY实现左侧TIPS滑进滑出效果示例
2013/06/27 Javascript
jQuery浏览器CSS3特写兼容实例
2015/01/19 Javascript
AngularJS学习笔记之TodoMVC的分析
2015/02/22 Javascript
深入理解JavaScript系列(48):对象创建模式(下篇)
2015/03/04 Javascript
分享我的jquery实现下拉菜单心的
2015/11/29 Javascript
基于d3.js实现实时刷新的折线图
2016/08/03 Javascript
解析JavaScript实现DDoS攻击原理与保护措施
2016/12/26 Javascript
jquery Form轻松实现文件上传
2017/05/24 jQuery
详解设置Webstorm 利用babel将ES6自动转码成ES5
2017/12/20 Javascript
Vue-cli配置打包文件本地使用的教程图解
2018/08/02 Javascript
使用vue点击li,获取当前点击li父辈元素的属性值方法
2018/09/12 Javascript
使用python删除nginx缓存文件示例(python文件操作)
2014/03/26 Python
python模拟鼠标拖动操作的方法
2015/03/11 Python
python f-string式格式化听语音流程讲解
2019/06/18 Python
python 利用turtle模块画出没有角的方格
2019/11/23 Python
CSS3 实现发光边框特效
2020/11/11 HTML / CSS
h5使用canvas画布实现手势解锁
2019/01/04 HTML / CSS
JAKO-O德国野酷台湾站:德国首屈一指的婴幼童用品品牌
2019/01/14 全球购物
Travelstart沙特阿拉伯:廉价航班、豪华酒店和实惠的汽车租赁优惠
2019/04/06 全球购物
开办化妆品公司创业计划书
2013/12/26 职场文书
2014年个人业务工作总结
2014/11/17 职场文书
学校办公室主任岗位职责
2015/04/01 职场文书
爱国教育主题班会
2015/08/14 职场文书
个人业务学习心得体会
2016/01/25 职场文书
使用Html+Css实现简易导航栏功能(导航栏遇到鼠标切换背景颜色)
2021/04/07 HTML / CSS
Python中的xlrd模块使用整理
2021/06/15 Python
python playwrigh框架入门安装使用
2022/07/23 Python