我的编程空间,编程开发者的网络收藏夹
学习永远不晚

什么?函数类型重载还可以动态生成?

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

什么?函数类型重载还可以动态生成?

重载是指一个函数可以有不同的参数和返回值,也就是有不同的函数签名。

ts 支持函数重载,可以为同一个函数定义多个不同的类型:

重载的写法一共有三种(估计大多数人只会一种):

declare function func(name: string): string;
declare function func(name: number): number;

这种大家比较常用,声明两个同名函数,就能达到重载的目的:

函数可以用 interface 的方式声明,同样,也可以用 interface 的方式声明函数重载:

函数类型可以取交叉类型,也就是多种类型都可以,其实也是函数重载的意思:

重载虽然是很有用的特性,但有的时候重载多了写起来还是挺麻烦的。

比如 ts 提供的 lib.dom.ts 里就有这样的类型定义:

因为每种参数对应不同的返回值,所以它就重载了这么多。

这样写起来也太麻烦了吧,能不能用类型编程动态生成呢?

考虑下重载的三种写法,declare 和 interface 不行,但是 & 可以呀,能不能我传入一个联合类型,然后它给返回交叉类型呢?

比如这样:

都提示出来了肯定是可以的,我们看下砸实现的吧:

联合转交叉函数参数有逆变的性质,也就是类型缩小,比如参数能同时传 A、B、C 的话,参数类型怎么定义?

肯定是 A、B、C 的交集呀,也就你 A & B & C 的交叉类型,这样就可以接收 A、B、C 的参数了。

可以利用这个性质实现联合转交叉。

比如这样:

都提示出来了肯定是可以的,我们看下砸实现的吧:

联合转交叉

函数参数有逆变的性质,也就是类型缩小,比如参数能同时传 A、B、C 的话,参数类型怎么定义?

肯定是 A、B、C 的交集呀,也就你 A & B & C 的交叉类型,这样就可以接收 A、B、C 的参数了。

可以利用这个性质实现联合转交叉。

type UnionToIntersection<U> = 
(U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown
? R
: never

测试一下:

这里的类型参数 U 是传入的联合类型,加一个 U extends U 是为了触发分布式条件类型的特性。

什么是分布式条件类型呢?

当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

比如这样一个联合类型:

type Union = 'a' | 'b' | 'c';

我们想把其中的 a 大写,就可以这样写:

type UppercaseA<Item extends string> = 
Item extends 'a' ? Uppercase<Item> : Item;

回到联合转交叉的这个高级类型:

加一个 U extends U 或者 U extends any 就能触发分布式条件类型的特性,让联合类型分成每一个类型单独传入做计算,最后把结果合并成联合类型。

然后再把它放到函数参数的位置,构造一个函数类型,通过模式匹配的方式提取参数的类型到 infer 声明的局部变量 R 里返回。

这样的结果就是交叉类型。

原因上面说过了,函数参数有逆变的性质,传入联合类型会返回交叉类型。

实现了联合转交叉之后,函数重载也就可以写出来了:

比如三个重载的返回值分别是 Aaa、Bbb、Ccc:

我们想基于这个生成重载的类型定义,传入联合类型返回重载的函数:

就可以这样写:

type UnionToOverloadFunction<T extends keyof ReturnValueMap> = 
UnionToIntersection<
T extends any ? (type: T) => ReturnValueMap[T] : never
>;

类型参数 T 是 ReturnValueMap 里的 key,约束为 keyof ReturnValueMap。

通过 T extends any 触发联合类型在分布式条件类型中的分发特性,让 'aaa' 'bbb' 'ccc' 分别传入做计算,返回构造出的函数类型的联合。

我们先单独测试下这部分:

可以看到返回的是构造出的函数类型的联合类型。

然后就用上面的 UnionToIntersection 转交叉就可以了:

这样就实现了重载函数的动态生成:

对比下最开始那种写法:

是不是清爽多了!而且还可以写一些动态逻辑。

总结

ts 函数重载一共有三种写法:declare function、interface、交叉类型 &。

当重载比较多的时候,直接列出来还是比较麻烦的,这时候可以用类型编程来动态生成函数重载。

我们实现了联合转交叉,利用了函数参数的逆变性质,也就是当参数可能是多个类型时,会返回它们的交叉类型。

然后又利用分布式条件类型的性质,当传入联合类型时,会把类型单独传入做计算,最后把结果合并成联合类型。

利用这个实现了传入联合类型返回构造出的函数的联合类型,然后再结合联合转交叉就实现了函数重载的动态生成。

当你写重载写的太多的时候,不妨试一下用类型编程的方式动态生成吧!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

什么?函数类型重载还可以动态生成?

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

什么?函数类型重载还可以动态生成?

ts 函数重载一共有三种写法:declare function、interface、交叉类型 &。当重载比较多的时候,直接列出来还是比较麻烦的,这时候可以用类型编程来动态生成函数重载。

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录