-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Generics; ReturnType<Foo> != ReturnType<typeof foo> #24277
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
|
Isn't
But it's saying that |
ah. sorry about that, did not see the call there.. yes. you are right about that. |
I don't know why I didn't think of this shorter example. function executeGeneric<
DelegateT extends () => number
>(delegate: DelegateT): ReturnType<DelegateT> {
//Type 'number' is not assignable to type 'ReturnType<DelegateT>'.
const x: ReturnType<typeof delegate> = delegate();
//Type 'number' is not assignable to type 'ReturnType<DelegateT>'.
const y: ReturnType<DelegateT> = delegate();
//Type 'number' is not assignable to type 'ReturnType<DelegateT>'.
return delegate();
} |
This is a suggestion, not a bug. Direct function calls are evaluated according to their constraints. This is generally desirable: function invokeAndMultiply<T extends () => number>(a: T, b: T) {
// OK or no?
return a() * b();
} In general you cannot multiply arbitrary types, so this example would be an error if we forced deferral of It'd be a pretty substantial complexity trade-off to start deferring the return type evaluation, since anything you do with a generic type constrained to a function type would then need follow-on special handling. |
Let's say we defer the evaluation of In this example, even if TS hasn't evaluated what And because of that, it should allow their multiplication, because you can multiply two My example is simple. So, deferring the evaluation of the type is also not an issue. In general, if given this, function foo<F extends () => T> (f : F) : ReturnType<F> {
/*
Current behaviour:
`value` is of type `T`.
Proposed behaviour:
`value` is of type `(T & ReturnType<F>)`,
where evaluation of `ReturnType<F>` is deferred.
*/
const value = f();
//Right now, we can do all things `T` can do because `value` is subtype of `T`.
/*
This should now work because `(T & ReturnType<F>)` extends `ReturnType<F>`.
*/
return value;
} Actually, I don't know anything about the compiler internals but I'm quite pleased with the above suggestion =x |
What additional feedback would be useful on this request? I filed a duplicate in #47900. My real-world use case boils down to this: interface IReadable {
read(): number | string;
}
class Reader<R extends IReadable> {
constructor(private _reader: R) {}
read(): ReturnType<R["read"]> {
return this._reader.read(); // error :(
}
}
let num = new Reader({ read: () => 1 }).read(); // inferred as number
let str = new Reader({ read: () => "1" }).read(); // inferred as string |
TypeScript Version: Version 2.9.0-dev.20180516
Search Terms: generic function returntype
I couldn't think of a good title for this,
Code
Expected behavior:
Return successfully.
Intuitively, to me,
delegate
is of typeDelegateT
.ReturnType<DelegateT>
andReturnType<typeof delegate>
should be the sameHowever,
Actual behavior:
Type 'X' is not assignable to type 'ReturnType<DelegateT>'.
Playground Link: Here
Related Issues:
The text was updated successfully, but these errors were encountered: