-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Assume type X = <T>() => Z<T>;
as having an optionnal generic type parameter to enable deducing the return type on generic methods
#57102
Comments
type X = <T>() => Z<T>;
as having an optionnal generic type parameter to enable deducing the return type on generic methodstype X = <T>() => Z<T>;
as having an optionnal generic type parameter to enable deducing the return type on generic methods
It seems there is a workaround if we know the class : type Z<T> = {val: T};
class Test {
build<T>(): Z<T> {
throw new Error();
}
}
function inferHelper<Klass extends Test, T>() {
type test = Klass["build"];
let a:test = {} as any;
return a<T>
}
type Return = ReturnType<ReturnType<typeof inferHelper<Test, number>>>; // Return = {val: number} However, if we don't know the class : abstract class Builder {
abstract build<T>(): any;
}
class Test extends Builder { ... }
function inferHelper<Klass extends Builder, T>() { ... }
type Ret<Klass extends Builder> = ReturnType<ReturnType<typeof inferHelper<Klass, number>>>;
type Return = Ret<Test> // Return = any instead of Return = {val: number} |
I'd interpret this as a request for "instantiation types" as opposed to instantiation expressions as implemented in #47607 (which cannot directly be used to get this functionality, as you note above, and as mentioned in #47607 (comment)). Also cross-linking #53410 |
Thanks for your answer. I read in #47607 (comment)) that the syntax
I would disagree with that, but if it is an issue, then, why not a
Solution:type GFoo<U> = AsGeneric<Foo, U>; // GFoo<U> = <U>() => U
type SFoo = GFoo<string> // SFoo = <string>() => string
type SFoo = AsGeneric<Foo, string>; // SFoo = <string>() => string |
That isn't just academic wheel-spinning, for what it's worth. It's a real issue, e.g. what would TS do here? type Foo<T = string> = <U>(x: T) => U;
type Bar = Foo<number>; Does
|
Knowing that we can write type Bar = Foo<number> // = <U>(x: number) => U;
type Bar = Foo<><number> // = number)(x: string) => number |
I found it strange so I made some tests : {
class BaseClass<V> {
protected fake(): V { throw new Error("") }
}
class Klass<V> extends BaseClass<V>{}
type Constructor<P extends BaseClass<number>> = new () => P;
type inferTest<T> = T extends Constructor<infer P> ? P :never;
type U = inferTest<Constructor<Klass<number>>> // U = Klass<number>
} But when we add a generic type parameter : {
class BaseClass<V> {
protected fake(): V { throw new Error("") }
}
class Klass<V> extends BaseClass<V>{}
type Constructor<V, P extends BaseClass<V>> = new () => P;
type inferTest<V, T> = T extends Constructor<V, infer P> ? P :never;
type U = inferTest<number, Constructor<number, Klass<number>>> // U = BaseClass<number>
} Is this a bug or an intended behavior ? |
I tried to do a minimal reproducible example, and I think I found the issue. Functions return type are computed only once, when declaring the function, however the return type isn't precise enough. {
class Base {
get self(): Base { return this }
}
class Child extends Base {
override get self(): Child { return this }
}
function convert<T extends Base>(X: T) {
return X.self;
}
const value = convert( new Child() );
// expected: typeof value = Child.
// got: typeof value = Base.
}
However, this would cause issue when the method/attribute has a generic, requiring to use |
Another solution would be to make use of the type X<T> = <T>() => {val: T};
type Y = <T>() => {val: T, child: true}
type Z = Y satisfies X<string> // Z = <string>() => {val: string, child: true} |
Duplicate #50481 and others. The proposed solution isn't really tractable IMO; it's very problematic for the same syntax to do two completely different things. |
What about the other suggestion : I don't know what syntax would be the best, but we do need such feature as there is currently no workaround for it. |
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
"ReturnType","generic method"
β Viability Checklist
β Suggestion
Given the following types :
I suggest we should be able to give a generic type parameter to the types :
π Motivating Example
When having classes with a generic method :
We can get the method as :
type X = Klass["method"]
which would betype X = <T>() => Z<T>
.However, to my knowledge, there are currently no ways to get the return type like :
We can only do :
However, it is possible to do :
π» Use Cases
Get the returned type of a generic method.
There are no current approaches to my knowledge.
Couldn't find any. If you find some, I'm interested.
The text was updated successfully, but these errors were encountered: