如何使泛型函数值?

时间:2019-02-04 05:06:44

标签: typescript

考虑以下代码:

interface Foo<T1> {
  foo: string;
  baz: T1;
}

function toFoo<T2>(value: T2): Foo<T2> {
  return {
    foo: 'bar',
    baz: value
  };
}

// Actually this function is imported from an NPM package so I can't change it
// The example is given for a better illustration
function memoize<T3, T4>(func: (arg: T3) => T4): (arg: T3) => T4 {
  // Some implementation...
  return func;
}

const memoizedToFoo: {<T5>(value: T5): Foo<T5>} = // ???

toFoo函数是通用的。我也需要制作一个通用的toFoo的记忆版本。我无法更改memoize的类型和实现。如何实现memoizedToFoo使其与给定的接口匹配?

我尝试了一下,但是没用:

const memoizedToFoo<T5> = memoize(toFoo<T5>); // unexpected <T5>

2 个答案:

答案 0 :(得分:3)

您可以更改memorize()函数吗?工作太辛苦了。

以下内容将自动推断正确的类型:

interface Foo<T1> {
  foo: string;
  baz: T1;
}

function toFoo<T2>(value: T2): Foo<T2> {
  return {
    foo: 'bar',
    baz: value
  };
}

function memoize<F extends Function>(func: F): F {
  // Some implementation...
  return func;
}

const memoizedToFoo = memoize(toFoo)

Playground link

更新:由于您无法更改memorize(),因此可以按如下所示很好地覆盖它:

// memorize.ts
import { memoize as origMemoize } from 'memoize'
// or if it is commonJS
import origMemoize from 'memoize'

export const memoize = origMemoize as <F extends Function>(func: F) => F

然后您就可以像原来一样使用它:

import { memoize } from './memoize'

// code away

请注意,此解决方案确实权衡了某些类型安全性,因为F不限于(arg: X) => Y

要正确解决此问题,我们需要: https://github.com/Microsoft/TypeScript/pull/22368

答案 1 :(得分:0)

使用any泛型参数(如果需要)来创建记忆函数,并将其转换为泛型类型:

const memoizedToFoo: <T5>(value: T5) => Foo<T5> = memoize(toFoo);
// or
const memoizedToFoo: typeof toFoo = memoize(toFoo);