通用memoize函数返回相同的函数类型

时间:2017-04-13 02:28:16

标签: typescript memoization

我正在尝试编写一个memoize函数,它将函数作为参数并返回一个类似的memoized函数。

function memoize<T extends Function, R>(f: T): T {
  const memory = new Map<string, R>();

  const g = (...args: any[]) => {
    if (!memory.get(args.join())) { memory.set(args.join(), f(...args)); }
    return memory.get(args.join());
  };

  return g; // g as T => [ts] Type '(...args: any[]) => R' cannot be converted to type 'T'.
}

// const exp: (...args: any[]) => RegExp
const exp = memoize<(text: string) => RegExp, RegExp>((text: string) => {
  return new RegExp(text.replace(/[^a-zA-Z0-9\s]/g, ".").replace(/\s+/g, "\\s+"), "ig");
});

问题在于,如果我只返回g,则exp的签名变为(...args: any[]) => RexExp,如果我尝试强制g为T,则ts会抱怨g不可分配到T

有没有办法“强迫”g成为同一类型的f,以便exp将完全相同的函数类型传递给memoize }?

1 个答案:

答案 0 :(得分:4)

这似乎有效:

function memoize<R, T extends (...args: any[]) => R>(f: T): T {
    const memory = new Map<string, R>();

    const g = (...args: any[]) => {
        if (!memory.get(args.join())) {
            memory.set(args.join(), f(...args));
        }

        return memory.get(args.join());
    };

    return g as T;
}

const exp = memoize((text: string) => {
    return new RegExp(text.replace(/[^a-zA-Z0-9\s]/g, ".").replace(/\s+/g, "\\s+"), "ig");
});

code in playground