【问题标题】:Use Generics to get a typed result of my little compose function使用泛型获取我的小 compose 函数的类型化结果
【发布时间】:2020-10-18 10:50:37
【问题描述】:

我的compose函数其实很简单:

const compose = (outer: any, inner: any) => (...innerParams: any) =>
  outer(inner(...innerParams));

当我现在这样做时:

const theInner = (p1: string, p2: string): string => [p1, p2].join(' ');
const theOuter = (p1: string): number => p1.length;

const theComposed = compose(theOuter, theInner);
const theResult = theComposed('asdf', 'asdf');

当我将鼠标悬停在 theComposedtheResult 上时,VSCode 的类型提示会显示 const theComposed: (...innerArgs: any) => any 我得到 const theResult: any
所以所有类型都丢失了。

我一直在尝试几种方法来使用泛型来完成这项工作,但不幸的是,我似乎无法解决这个问题。

这是我的失败之一:

export const compose = <
  T extends CallableFunction,
  U extends CallableFunction,
  PT extends ThisParameterType<U>
>(
  outer: T,
  inner: U
) => (...args: PT[]) => outer(inner(args));

这导致theComposed 显示const theComposed: (...args: unknown[]) =&gt; anytheResult 仍然是任何。
无论如何,我为返回类型尝试的大多数事情都只会让 typescript 编译器对我发火。

我想要的结果是:

const theComposed: (p1: string, p2: string) => number

这样可行吗?

TIA。

https://stackblitz.com/edit/typescript-wut8jg

【问题讨论】:

标签: typescript typescript-generics


【解决方案1】:

怎么样?

type InnerFunction<T extends unknown[], V> = (...args: T) => V; 
type OuterFunction<V,W> = (arg: V)=> W; 

const compose = <T extends unknown[], V, W>(
    outer: OuterFunction<V, W>, 
    inner: InnerFunction<T,V>
) => (...innerParams: T) =>
  outer(inner(...innerParams));

const theComposed = compose(theOuter, theInner);
const theResult = theComposed('asdf', 'asdf');

Playground Link

说明

当然,您的第一种方法,即声明 any 类型是行不通的,因为您显式地扩大了类型,而且正如您所说,问题是类型信息丢失了。

所以使用泛型,我发现最简单的方法是先声明几个中间类型,然后使用这些类型来创建 compose 函数的类型。

首先:

type InnerFunction<T extends unknown[], V> = (...args: T) => V; 

这里,我们说InnerFunction 类型是一个函数,它有未知的参数,并返回一个V 类型的值。

type OuterFunction< V,W> = (arg: V)=> W; 

这里我们说OuterFunction 类型是一个函数,它需要一个V 类型(按照惯例,我只是使用与内部返回类型相同的字母,但它没有任何效果),并返回一个W类型的值。

把这些放在一起,我们只是用我们的内部和外部函数声明了 compose 函数,我们只需要让所有的泛型参数都可用。

为此,我们只需在函数圆括号之前的尖括号中声明它们。

const compose = <T extends unknown[], V, W>(
    outer: OuterFunction<V, W>, 
    inner: InnerFunction<T,V>
)

现在,重要的部分是我们声明的V 泛型参数在外部函数和内部函数之间共享。这就是我们如何保持内部函数的返回值与外部函数的参数类型相同。

【讨论】:

  • 完美。谢谢分配?
  • 我想我可以用同样的方法修复我的 pipe()。那一个减少了撰写...非常感谢!
猜你喜欢
  • 1970-01-01
  • 2018-10-04
  • 2020-11-15
  • 2021-06-16
  • 2020-05-13
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
相关资源
最近更新 更多