【问题标题】:Generic memoize function returning the same function type通用 memoize 函数返回相同的函数类型
【发布时间】:2017-04-13 02:28:16
【问题描述】:

我正在尝试编写一个 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[]) =&gt; RexExp 并且如果我试图强制 g 为 T,那么 ts 抱怨 g 不能分配给 T

有没有办法“强制”gf 相同类型,以便 exp 将完全相同类型的函数传递给 memoize

【问题讨论】:

  • args.join() 不适合作为键:您对获取对象的函数有问题,因为例如,[{}].join()[{foo: 'bar'}].join() 返回相同的值:"[object Object]"。仅使用args 作为映射键并没有更好,因为映射使用严格相等,因此“非严格相等”值将被多次记忆。
  • @artem 感谢 cmets。你是对的,那不是一把好钥匙。看起来使用地图构建树会是更好的解决方案。

标签: typescript memoization


【解决方案1】:

这似乎有效:

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    相关资源
    最近更新 更多