-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Can't assign result of function of type T to ReturnType<T> #31811
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
Comments
The error actually kind of makes sense to me, at least.
I guess the compiler isn't smart enough to realize that |
Hmm, the plot thickens. The IntelliSense hover text for (p: number) => IFoo Normally for variables of generic types it will say the type is |
Well, within the body of the generic function it doesn't actually know what Let's see if someone else smarter comes along to solve this mystery because I'm out of ideas. 😛 |
The type-checking looks reasonable - it knows that factory function is generic, it's just the quick info that is slightly off. function createSomeInterfaceInstance<T extends (p: number) => IFoo>(factoryFunction: T): ReturnType<T> {
const fun: T = factoryFunction; // hover factoryFunction: (parameter) factoryFunction: T extends (p: number) => IFoo
return fun(12); // hover fun: const fun: T (p: number) => IFoo
// ^ the generic is here, but in a weird place.
} TypeScript doesn't know how to apply a generic parameter, so it attempts to find a function-like constraint and apply that - this is why the return type is The solution:
Doesn't feel hacky to me and is inline with TypeScript guidelines that suggests pushing type-parameters down as far as possible. Though I would write it as follows, unless you really need function createSomeInterfaceInstance<R>(factoryFunction: (p: number) => R): R {
return factoryFunction(12);
}
const instance: Foo = createSomeInterfaceInstance(Foo.create); |
You're right about that - I overlooked that
Thanks @jack-williams! |
In order for the original example to work the type checker would have to consider the type of the call expression I'll echo what @jack-williams said above. The best way to write it is: function createSomeInterfaceInstance<R>(factoryFunction: (p: number) => R): R {
return factoryFunction(12);
}
const instance: Foo = createSomeInterfaceInstance(Foo.create); |
TypeScript Version: [email protected]
Search Terms:
generic ReturnType, ReturnType assign
Explanation
TypeScript seems to treat the return type of a generic not as the
ReturnType<T>
but the type it extends from. Basically in this example we get a type error (even thoughinstance
is correctly inferred asFoo
) becauseIFoo
is not assignable toReturnType<T>
:Now this is hackable-around in two different ways, one by explicitly adding a generic for the return type of
T
e.g.:function createSomeInterfaceInstance<K extends IFoo, T extends (p: number) => K>(factoryFunction: T): K
Or just by using a type intersection on the return type e.g.:
function createSomeInterfaceInstance<T extends (p: number) => IFoo & ReturnType<T>>(factoryFunction: T): ReturnType<T>
But both of these solutions feel pretty hacky, it would instead be better if TypeScript inferred the type of
factoryFunction(10)
to beIFoo & ReturnType<T>
instead of justIFoo
.Playground Link: playground-link
Related Issues:
Probably related: #29133
The text was updated successfully, but these errors were encountered: