typescript - 在 Typescript 中优雅地相交两种函数类型
问题描述
我有这两种功能类型..
wrapPageElement?(
args: WrapPageElementBrowserArgs<DataType, PageContext, LocationState>,
options: PluginOptions
): React.ReactElement
.. 和 ..
wrapPageElement?(
args: WrapPageElementNodeArgs<DataSet, PageContext>,
options: PluginOptions
): React.ReactElement
所以它们几乎相同,除了args
. 差异对我的用例无关紧要。我可以完全依赖这两者之间的交叉类型。我写了以下类型:
type Params1 = Parameters<GatsbyBrowser['wrapPageElement']>
type Params2 = Parameters<GatsbySSR['wrapPageElement']>
type Return1 = ReturnType<GatsbyBrowser['wrapPageElement']>
type Return2 = ReturnType<GatsbySSR['wrapPageElement']>
type WrapPageElement = (args: Params1[0] | Params2[0], options: Params1[1] | Params2[1]) => Return1 | Return2;
这是一个最小的复制。这是可行的,但是是否可以WrapPageElement
更优雅地编写类型或者这是要走的路?
Tl;博士
type PluginOptions = object;
type ReactElement = object;
type WrapPageElementBrowserArgs = {element: object, browserArgs: object};
type WrapPageElementNodeArgs = {element: object, nodeArgs: object};
type GatsbyBrowser = {
wrapPageElement: (
args: WrapPageElementBrowserArgs,
options: PluginOptions
) => ReactElement
}
type GatsbySSR = {
wrapPageElement: (
args: WrapPageElementNodeArgs,
options: PluginOptions
) => ReactElement
}
type Params1 = Parameters<GatsbyBrowser['wrapPageElement']>
type Params2 = Parameters<GatsbySSR['wrapPageElement']>
type Return1 = ReturnType<GatsbyBrowser['wrapPageElement']>
type Return2 = ReturnType<GatsbySSR['wrapPageElement']>
type WrapPageElement = (args: Params1[0] | Params2[0], options: Params1[1] | Params2[1]) => Return1 | Return2;
type WrapPageElement2 = GatsbyBrowser['wrapPageElement'] & GatsbySSR['wrapPageElement']; // not what I need
解决方案
您正在寻找一种类型转换,它采用两种函数类型T
并将U
它们转换为单个函数类型,其中每个参数和返回类型是相应参数和来自and的返回类型的联合。T
U
我将这种转变称为UnionFunctions<T, U>
需要一个更好的术语。您提到了函数的“相交”,但是 TypeScript 中的函数类型的交集相当于具有多个调用签名的函数的类型(即重载函数),并且与取每个参数的并集和返回不同类型。
无论如何,一种可能的方法是:
type UnionTuples<T extends any[], U extends { [K in keyof T]: any }> =
{ [K in keyof T]: T[K] | U[K] }
type UnionFunctions<T extends (...args: any[]) => any, U extends (...args: any) => any> =
(...args: UnionTuples<Parameters<T>, Parameters<U>>) => ReturnType<T> | ReturnType<U>
这里UnionTuples<T, U>
需要两个元组T
andU
并产生一个元组,其中每个元素是来自 和 的相应元素的T
并集U
。UnionTuples<[1, 2], [3, 4]>
应该如此[1 | 3, 2 | 4]
。这是一个简单的映射元组类型。
然后UnionFunctions
只UnionTuples
在参数列表中使用T
and U
(使用实用程序类型),返回类型是使用实用程序类型的返回类型Parameters<T>
的联合ReturnType<T>
。
定义它并不是非常冗长UnionFunctions
,但是编写它比编写手动版本需要更多的字符。您需要UnionFunctions
多次使用或使用长参数列表才值得。
让我们看看它是否适用于您的示例:
type WrapPageElement = UnionFunctions<
GatsbyBrowser['wrapPageElement'],
GatsbySSR['wrapPageElement']
>
/* type WrapPageElement = (
args: WrapPageElementBrowserArgs | WrapPageElementNodeArgs,
options: PluginOptions
) => ReactElement */
看起来挺好的!
推荐阅读
- python - 将 Python 脚本与 scipy 和 numpy 库以及 Unity 一起使用的任何可行方法?
- javascript - 赛普拉斯等待所有 ajax 请求
- xamarin - Xamarin.forms 根据日期检索 Firebase 数据
- python - 在 Python 列表中按字典 ID 查找元素[字典]
- java - 如何将 txt 文件中的单词或数字声明为字符串
- spring - 用于安排 CRON 作业在周二至周六早上 6 点运行的 spring CRON 表达式?
- mongodb - 将 spring-boot-starter-data-mongodb 更新到更新版本
- android - Android:MotionLayout 无法将视图可见性设置为消失,视图保持可见
- ggplot2 - 图例未显示带有 2 个 x 轴的 ggplot2
- java - 无法连接到基于 Docker 的 Cassandra 容器 - “所有主机尝试查询失败”