-
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? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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: typescript@3.6.0-dev.20190606
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: