重载是什函数类指一个函数可以有不同的参数和返回值,也就是型重有不同的函数签名。 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 extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never 测试一下: 这里的类型参数 U 是传入的联合类型,加一个 U extends U 是为了触发分布式条件类型的特性。 什么是分布式条件类型呢? 当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,云南idc服务商TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。 比如这样一个联合类型: type Union = a | b | c; 我们想把其中的 a 大写,就可以这样写: type UppercaseA Item extends a ? Uppercase 回到联合转交叉的这个高级类型: 加一个 U extends U 或者 U extends any 就能触发分布式条件类型的特性,让联合类型分成每一个类型单独传入做计算,最后把结果合并成联合类型。 然后再把它放到函数参数的位置,构造一个函数类型,通过模式匹配的方式提取参数的类型到 infer 声明的局部变量 R 里返回。 这样的结果就是交叉类型。 原因上面说过了,函数参数有逆变的性质,传入联合类型会返回交叉类型。 实现了联合转交叉之后,函数重载也就可以写出来了: 比如三个重载的返回值分别是 Aaa、Bbb、Ccc: 我们想基于这个生成重载的类型定义,传入联合类型返回重载的函数: 就可以这样写: type UnionToOverloadFunction 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、交叉类型 &。 当重载比较多的时候,直接列出来还是比较麻烦的,这时候可以用类型编程来动态生成函数重载。 我们实现了联合转交叉,利用了函数参数的逆变性质,也就是当参数可能是多个类型时,会返回它们的交叉类型。 然后又利用分布式条件类型的性质,当传入联合类型时,会把类型单独传入做计算,最后把结果合并成联合类型。 利用这个实现了传入联合类型返回构造出的函数的联合类型,然后再结合联合转交叉就实现了函数重载的动态生成。 当你写重载写的太多的时候,不妨试一下用类型编程的方式动态生成吧!