You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Trying to get the type of a generic method of a class results in a parse error #53410
I'm not able to get the type of a generic method in a class. It results in a parse error.
🙂 Expected behavior
Getting type of a generic method of a class should be possible.
Additional information
I need this to get the return type of a generic function from within to cast the return result (a workaround to to the bug with generic conditionals not resolving in certain cases).
It's not possible to just create a separate type to hold a reference to the method type because that type is not going to be a generic, and if you try to make a generic type out of it, it will result in the same problem. I'm not aware of any workarounds.
I don't know what <'test'> is supposed to mean in your example. You can get the return type using ReturnType<Foo['bar']>. However, as this is an unbound generic type you'll either get the type of the constraint (if any), or unknown.
ReturnType<Foo['bar']> would not do, it would only default to what the extends clause is, but I need a more narrow subtype. I can get this with functions but I cannot do this with methods because of this issue.
I don't know what you mean by "a more narrow subtype". At that point there is no more narrow subtype. The function is generic, the type is provided at call site, there's no concrete type available.
My real world case is that the generic extends { id: string } so the actual generic can have more properties defined in the shape, i.e. { id: string, title: string} In that case, doing ReturnType<Foo['bar']> would default the generic to { id: string } but I need to be able to pass the generic in that return type so I can get { id: string, title: string} for instance. It's more complex than that too, the return type is a conditional that depends on the input generic, generic type narrowing does not work fully, so I need to cast the return type as precisely the return type of the method with the generic argument that was passed so I can bypass the error with casting.
The first code snippet in this comment is what I'm trying to do, except with classes: #53318 (comment)
The core issue here is that it's not possible to get the full type of a class method (as a generic).
Joe Calzaretta (@jcalz) Makes it clear what he actually (probably) wanted and what the meaning of the <"test"> was: Wanting to get the return type after providing a concrete type for the generic argument.
Good catch, Joe Calzaretta (@jcalz) - I knew it was an attempt at an instantiation expression, but I admit I also thought it was a bug that it didn’t work. See, what’s frustrating is that you can do…
…and that makes perfect sense, so it does ultimately seem natural to expect this kind of thing to work. It’s that pesky subtle distinction between “generic function type” and “concrete function type with generic type parameters” that gets in the way.
Thanks, much appreciated. Yes, that was a little confusing, especially since I thought that in the example type x = Foo['bar'] would be a regular type. whzx5byb 's solution is perfect.
Edit: The prototype solution is not going to work if the class has a generic too.
Maciej Kravchyk (@mckravchyk) Yeah, there’s a confusing distinction here in that type Foo<T> = () => T is a generic type that evaluates to a concrete, non-generic function type (i.e. it’s a type function), while type Foo = <T>() => T is the concrete, non-generic type of a generic function. Foo['bar'] gives you the latter, so you can’t pass type parameters to it.
Reacted by Ryan Cavanaugh, Maciej Kravchyk and btoo
Activity
MartinJohns commentedon Mar 21, 2023
I don't know what
<'test'>is supposed to mean in your example. You can get the return type usingReturnType<Foo['bar']>. However, as this is an unbound generic type you'll either get the type of the constraint (if any), orunknown.mckravchyk commentedon Mar 21, 2023
The T generic of the method.
ReturnType<Foo['bar']>would not do, it would only default to what the extends clause is, but I need a more narrow subtype. I can get this with functions but I cannot do this with methods because of this issue.MartinJohns commentedon Mar 21, 2023
I don't know what you mean by "a more narrow subtype". At that point there is no more narrow subtype. The function is generic, the type is provided at call site, there's no concrete type available.
mckravchyk commentedon Mar 21, 2023
My real world case is that the generic extends
{ id: string }so the actual generic can have more properties defined in the shape, i.e.{ id: string, title: string}In that case, doingReturnType<Foo['bar']>would default the generic to{ id: string }but I need to be able to pass the generic in that return type so I can get{ id: string, title: string}for instance. It's more complex than that too, the return type is a conditional that depends on the input generic, generic type narrowing does not work fully, so I need to cast the return type as precisely the return type of the method with the generic argument that was passed so I can bypass the error with casting.The first code snippet in this comment is what I'm trying to do, except with classes: #53318 (comment)
The core issue here is that it's not possible to get the full type of a class method (as a generic).
jcalz commentedon Mar 21, 2023
This is working as intended, not a bug. Instantiation expressions are expressions, not types. You can't write
Instead you'd need to write
You simply must drop to value space to do this; it can't be done purely at the type level. In your code above it could look like
MartinJohns commentedon Mar 21, 2023
Joe Calzaretta (@jcalz) Makes it clear what he actually (probably) wanted and what the meaning of the
<"test">was: Wanting to get the return type after providing a concrete type for the generic argument.fatcerberus commentedon Mar 21, 2023
Good catch, Joe Calzaretta (@jcalz) - I knew it was an attempt at an instantiation expression, but I admit I also thought it was a bug that it didn’t work. See, what’s frustrating is that you can do…
…and that makes perfect sense, so it does ultimately seem natural to expect this kind of thing to work. It’s that pesky subtle distinction between “generic function type” and “concrete function type with generic type parameters” that gets in the way.
whzx5byb commentedon Mar 21, 2023
It is possible to access a method type from
prototype, sotype fType = typeof Foo.prototype.bar<string>will work for you.mckravchyk commentedon Mar 21, 2023
Thanks, much appreciated. Yes, that was a little confusing, especially since I thought that in the example
type x = Foo['bar']would be a regular type. whzx5byb 's solution is perfect.Edit: The prototype solution is not going to work if the class has a generic too.
fatcerberus commentedon Mar 21, 2023
Maciej Kravchyk (@mckravchyk) Yeah, there’s a confusing distinction here in that
type Foo<T> = () => Tis a generic type that evaluates to a concrete, non-generic function type (i.e. it’s a type function), whiletype Foo = <T>() => Tis the concrete, non-generic type of a generic function.Foo['bar']gives you the latter, so you can’t pass type parameters to it.