3

I'm doing a simple memoize function, what it does is that it takes a function and will do some magic where it caches the return result. But basically the types for the returned function for memoize is exactly the same as the given one. But I'm having errors which I don't know how to fix. When using the function while ignoring the errors I'm having, the types work.

I've made two functions to showcase my problem, from my perspective, both types should work but I'm getting closer with the second implementation, however it still doesn't work.

Here is a link to the TypeScript Playground but just in case it can expire I will post some code with some pictures that shows the errors:

function memoize1<F extends (...args: any[]) => Promise<any>>(func: F): F {
    return (...args) => func(...args)
}

function memoize2<F extends (...args: any[]) => Promise<any>>(func: F): (...args: Parameters<F>) => ReturnType<F> {
    return (...args) => func(...args)
}

const first = memoize1(() => {}) // Complains
const second = memoize1(async () => {}) // Works
const third = memoize2(() => {}) // Complains
const fourth = memoize2(async () => {}) // Works

Here are the error images, one for the first example and the second example

1

1 Answer 1

2

There is an interesting issue on githup according this behavior mentioned in your question. An explicit cast to the desired type should remove the compile errors, caused by the functions:

function memoize1<F extends (...args: any[]) => Promise<any>>(func: F): F {
    return ((...args) => func(...args)) as F
}

function memoize2<F extends (...args: any[]) => Promise<any>>(func: F): (...args: Parameters<F>) => ReturnType<F> {
    return (...args) => func(...args) as ReturnType<F>
}

The reason your memoize1 call fail, is because the given parameter function do not return a promise as specified by memoize1 F extends (...args: any[]) => Promise<any>

So calling memoize1(() => {}) passes a function wich return an empty object and not a promise. By using the async statement the function return type changes to promise. Thats why memoize1(async () => {}) work.

For example: const first = memoize1(() => new Promise((resolve, reject)=> {}) passes an function wich return a promise and would compile.

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

4 Comments

Sorry for the late response, doing this project outside of work. Your sentence regarding "The reason your memoize1 can fail, is beacuse...", I don't understand why my returned function doesn't return a promise. The types says that it needs to be a function that returns a promise and the returned function returns whatever the func is returning (in this case a promise).
I've tried doing what you have done but with more DRY typings (so I don't have to change the return type of the function twice) but TypeScript can't tell that what I've done is actually correct. Link to playground
I´v updated the anwser. Please let me know if it solved your issue.
Yep, this one works like a charm. I just don't understand from TypeScript perspective on why I need to typecast. But thanks for the help.

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.