2

I'm trying to implement a small caching function. While my implementation appears to work, I'm having a hard time defining the proper types in it.

type Producer<T> = (...args: any[]) => Promise<T>;

export function cache<T>(producer: Producer<T>): Producer<T> {
  let cached;
  return async function(...args: any[]): Promise<T> {
    if (!cached) {
      cached = await producer.apply(null, args);
    }
    return cached;
  };
}

Yes, I still have to improve it, so that the value is cached based on the passed parameters, but that's a minor and easy to fix issue.

a Producer in this case is a function that can produce a cacheable value and should only ever be called once. cache() returns a function that should have matching parameters to the producer passed to the cache() function. Now, this works perfectly fine right now if you know what parameters to pass, but this is TypeScript, so I would love the compiler to be able to validate the types. I just don't know how to define that the returned function should have the same parameters as the producer. I know that there are all these utility types in TS, but I cannot figure out how to use them in this case.

1 Answer 1

2

You can use Parameters utility to extract type of arguments of the producer function:

function cache<T, TProducer extends Producer<T>>(producer: TProducer): TProducer {
  let cached: Promise<T>;
  const wrapper = (...args: Parameters<TProducer>): Promise<T> => {
    if (!cached) {
      cached = producer(...args);
    }
    return cached;
  };

  return wrapper as TProducer;
}

Playground


Sign up to request clarification or add additional context in comments.

6 Comments

while your solution doesn't crash, it also doesn't solve the problem. now If I define const x = cache((param: String) => param); and try to call it with a wrong parameter like x(4), the compiler still doesn't complain
The only problem with previous approach was that return type of cached function wasn't properly inferred. Please check updated version
now it worked like a charm! Thank you! I am totally confused about how to interpret this and I will need some time for it to sink in, but it definitely solves my problem!
I'm good. I got it. But I wouldn't have come up with TProducer myself
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.