-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to replace return type of function type #39594
Comments
Very useful feature. This is the only way to implement |
This would indeed be a very useful feature! I think it might be incredibly useful to have a syntax for mapping over the entirety of a function type including type parameters and return type, similar to a mapping over object/tuple types. Does that sound useful to others in the thread? |
@TylorS We need to look at the code examples |
Just to add some life to this four-year-old issue. I have a use case of factories of factories. For example: interface CacheEntry<T> {
value: T
cachedAt: Date
}
// This is where I want to swap the return type
export function createCachedFactory<TFn extends (...args: any) => any>(factory: TFn) {
const cache: Record<string, CacheEntry<ReturnType<TFn>>> = {}
return (...args: Parameters<TFn>) => {
const cacheKey = JSON.stringify(args)
return cache[cacheKey] ??= { value: factory(...args), cachedAt: new Date() }
}
}
interface Foo1 { bar1: number }
export const makeFoo1 = createCachedFactory((bar1: number): Foo1 => ({ bar1 }))
interface Foo2<T> { bar2: T }
// This should be typed as: <T>(bar2: T) => CacheEntry<Foo2<T>>
export const makeFoo2 = createCachedFactory(<T>(bar2: T): Foo2<T> => ({ bar2 })) Here are some proposed solutions (in order of desirability, with most desirable at the top): // Proposal 1: TypeScript intelligently determines that the inferred parameters
// are used in the new parameters and the inferred return type is used in the
// new return type, so the new function type should be generic, if the original
// function type is generic
declare function createCachedFactory<TFn extends (...args: any) => any>(factory: TFn):
TFn extends (...args: infer TParams) => infer TRet
? (...args: TParams) => CacheEntry<TRet>
: (...args: Parameters<TFn>) => CacheEntry<ReturnType<TFn>>
// Proposal 2: similar to proposal 1, but TypeScript is using the utility types
// Parameters and ReturnType instead of directly inferred types
declare function createCachedFactory<TFn extends (...args: any) => any>(factory: TFn):
(...args: Parameters<TFn>) => CacheEntry<ReturnType<TFn>>
// Proposal 3: a special type is used to add handling of generic functions. I am
// not sure if this is really much easier to implement than proposal 1 or 2 as
// there still needs to be some guardrails to handle misusing or not
// inferring/using TParams and TRet
declare function createCachedFactory<TFn extends (...args: any) => any>(factory: TFn):
TFn extends GenericFunction<infer TParams, infer TRet>
? (...args: TParams) => CacheEntry<TRet>
: (...args: Parameters<TFn>) => CacheEntry<ReturnType<TFn>>
// Proposal 4: similar to proposal 3, but with additional special types for the
// parameters and return types
declare function createCachedFactory<TFn extends (...args: any) => any>(factory: TFn):
TFn extends GenericFunction
? (...args: GenericParameters<TFn>) => CacheEntry<GenericReturnType<TFn>>
: (...args: Parameters<TFn>) => CacheEntry<ReturnType<TFn>> |
Search Terms
Suggestion
I would like to be able to replace just the return type of a function with a utility type, like
WithReturn<F, R>
.I'm not 100% sure this is needed, but it seems like using
(...args: Parameters<F>) => R
is not sufficient because any generics inF
are lost.Use Cases
My use case is a utility function that captures the arguments to a function to allow it to be called later.
Examples
Right now there's an error because the generics to
map()
are lost when usingParameters
.Playground: https://www.typescriptlang.org/play/?ssl=13&ssc=1&pln=1&pc=1#code/KYDwDg9gTgLgBAYwgOwM7wCbAGbCnAXjgB4AxOUGYZDVOACgDpmBDKAc1QC44XkBPAJSEAfLwEj62HqWEEx9egCg4cZozaceABTYsAtsCpRUZEUrkKA3irjYArsgQwAlih7YANLc2pvAX0FhAHoAKl46Pn4IuHJQ4IBuJSUkNHh9FjBCEgAVTzgAJUk2KBZ+HgBBKFL+YhyRfOkGFx4cy0L2krLGDLApQSTU9DgsXGrgDABZTOzRvHpegeSAGyM4fCI58anM+gBtAEYAXXz6Frhke30AIzx2gCYlqA0OVCSgA
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: