Skip to content
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

Prefix <T> to access methods with generics : Klass[<T>"method"] #57297

Closed
6 tasks done
denis-migdal opened this issue Feb 5, 2024 · 5 comments
Closed
6 tasks done

Prefix <T> to access methods with generics : Klass[<T>"method"] #57297

denis-migdal opened this issue Feb 5, 2024 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@denis-migdal
Copy link

denis-migdal commented Feb 5, 2024

πŸ” Search Terms

generic methods

βœ… Viability Checklist

⭐ Suggestion

Use prefix <T> to access methods with generics:

class Klass {
    method<T>() {}
}

type Method = Klass[<number>"method"] // <number>() => void

Could also be extended for all <T>(...args: any[]) => any types :

type Fct = <T>() => void;
type FctT<U> = <U>Fct; // FctT<U> = <U>() => void;

I think there are no ambiguity with this syntax:

typeA<T>typeB  // syntax error
<T>typeA.typeB // = (<T>typeA).typeB
typeA.<T>typeB // = <T>(typeA.typeB)

πŸ“ƒ Motivating Example

Currently, there are no ways to access a method with generics from a class.

This would solve numerous issues :

πŸ’» Use Cases

  1. What do you want to use this for?

Access methods with generics

  1. What shortcomings exist with current approaches?

No current approaches.

  1. What workarounds are you using in the meantime?
@whzx5byb
Copy link

whzx5byb commented Feb 5, 2024

Workaround: access method from prototype.

type Method = typeof Klass.prototype.method<number>;

@denis-migdal
Copy link
Author

denis-migdal commented Feb 5, 2024

Workaround: access method from prototype.

type Method = typeof Klass.prototype.method<number>;

Nope.
You didn't "access a method with generics from a class" in TS, but asked the type of a value that happens to be a method.

class Klass {
	method<T>() {

	}
}

// from the class
type T = Klass;
type m1 = T["method"]

// from the type of the class
type TK = typeof Klass;
type m2 = TK["prototype"]["method"];

Your solution could work using functions :

function _getMethod<T extends BaseClass, U>(t: typeof T) {
      return t.prototype.method<U>;
}

type getMethod<T extends BaseClass, U> = ReturnType<typeof _getMethod<T, U>>

But due to Typescript widening, that will return BaseClass.prototype.method<U> instead of T.prototype.method<U>

cf #57286

Also, we could help TS by precising the return type :

function _getMethod<T extends BaseClass, U>(t: typeof T): T["prototype"]["method"] {
      return t.prototype.method<U>;
}

But we have currently no ways to precise the generic parameters to the type...

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Feb 5, 2024
@RyanCavanaugh
Copy link
Member

Nope. You didn't "access a method with generics from a class" in TS, but asked the type of a value that happens to be a method.

I don't understand what you're getting at here. @whzx5byb's answer isn't even a workaround; it's a solution.

I also don't see what this being in a class has to do with anything. There are existing issues around generic instantiation of a type as opposed to a value.

@denis-migdal
Copy link
Author

denis-migdal commented Feb 5, 2024

I also don't see what this being in a class has to do with anything. There are existing issues around generic instantiation of a type as opposed to a value.

My suggestion wasn't about generic instantiation of a type, but to be able to fetch a generic version of a method.
It is not (2 operations) :

  1. operator []: we fetch Klass["method"]
  2. operator <>: we make a generic instantiation of the returned type.

But (1 operation):

  1. operator [<> ]: we fetch Klass[<T>"method"] directly as a type.

Sorry if I'm not clear in my expression, I am not quite familiar with TS nomenclature and internal stuff.

I then suggested an extension to the syntax for a more generic usage, that is indeed a generic instantiation of a type.
Which would give (in the same case as above): <T>(Klass["method"]). So it is slightly different.

I made another issue as other issues doesn't seem active / followed.
I think I suggested a way that seems to not have the drawback of other cited suggestions:

  • no syntax ambiguity (?)
  • simple, clear and concise syntax.
  • I guess not too much trouble to implement (?).

Nope. You didn't "access a method with generics from a class" in TS, but asked the type of a value that happens to be a method.

I don't understand what you're getting at here. @whzx5byb's answer isn't even a workaround; it's a solution.

It isn't, as he gets the type from a value that happens to be a method, not from the class in TS.

When manipulating types, there are lot of cases where you don't have access to the values :

function foo<T extends Record<string, X>>(...) {

     type T2<U> = {
         [K in keyof T]: T[K][<U>"method"] // can't have access to the class value as we are in TS (type manipulation, not value manipulation).
     }
}

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants