Hookyns / tst-reflect

Advanced TypeScript runtime reflection system
MIT License
341 stars 11 forks source link

Method and Function overloads #63

Closed carloszimm closed 2 years ago

carloszimm commented 2 years ago

Hello folks!

I was wondering if there's an easy way to detect/list functions'/methods' overloads? At the README is listed "overloads of a constructors and methods supported," but I couldn't find a real example or snippet to guide me on that matter (though that shouldn't be hard to do it manually, that's why I bolded "an easy way" at the beginning).

Thanks in advance and great library!

Hookyns commented 2 years ago

type.getConstructors() returns list with constructor or its overloads. type.getMethods() returns list of methods with their overloads. Each overload is treated the same as method itself. Overload represents callable method. You can detect overloaded methods by grouping methods by name.

StackBlitz demo.

export class SomeClass {
  constructor();
  constructor(a?: boolean);
  constructor(b?: string);
  constructor(a: boolean, b?: string);
  constructor(aOrB?: boolean | string, b?: string) {}

  someMethod(a?: boolean);
  someMethod(b?: string);
  someMethod(aOrB?: boolean | string) {}

  someOtherMethod() {}
}

While writing the demo I figured out that method overloads does not work and we don't even have the unit test for that. I've prepared the fix, I'll publish that in the evening.

This is the output from that demo running with fixed version:

Constructors:
┌─────────┬───────────────┬──────────────┐
│ (index) │       0       │      1       │
├─────────┼───────────────┼──────────────┤
│    0    │               │              │
│    1    │ 'a?: Boolean' │              │
│    2    │ 'b?: String'  │              │
│    3    │ 'a: Boolean'  │ 'b?: String' │
└─────────┴───────────────┴──────────────┘
Methods:
┌─────────┬───────────────────┬───────────────────┐
│ (index) │         0         │         1         │
├─────────┼───────────────────┼───────────────────┤
│    0    │   'someMethod'    │ [ 'a?: Boolean' ] │
│    1    │   'someMethod'    │ [ 'b?: String' ]  │
│    2    │   'someMethod'    │   [ 'aOrB?: ' ]   │
│    3    │ 'someOtherMethod' │        []         │
└─────────┴───────────────────┴───────────────────┘
carloszimm commented 2 years ago

Got it. Thanks, @Hookyns! Looking forward to your fix :)

Hookyns commented 2 years ago

@carloszimm Implemented in tst-reflect@0.11.2 and tst-reflect-transformer@0.11.3.

carloszimm commented 2 years ago

@Hookyns I tested and it's working as expected (following your output posted above). I just have some questions.

1 - While the output for the "someMethod" listed the definitions as well as the implementation, the output for the constructor only included the definitions of it. Is that the expected output? 2 - The last output of "someMethod" didn't show the (union) type for the parameter. Is that the expected output? If so, should I invoke a different method for union types for example?

Hookyns commented 2 years ago
carloszimm commented 2 years ago

Gotcha (:

carloszimm commented 2 years ago
  • yeah, thats wrong. Implementation shoud not be visible. Ctors are ok, methods are not.

@Hookyns before closing this issue, should the above point still be flagged as a bug or it was a matter of modifying the code (solution) to detect those specific cases (methods)?

Hookyns commented 2 years ago

Still a bug for me until I fix that issue with listed implementation signature which. I think I'll be able to fix it today.

carloszimm commented 2 years ago

Important to note that it's an overload matter. If there wasn't overload, the output of the implementation signature would be ok :)

Hookyns commented 2 years ago

Sure 🙂

carloszimm commented 2 years ago

Hello again @Hookyns

So, I'm facing trouble when it comes to reflect on functions + overloads. To be more specific, I'm trying to reflect on functions exported by a library, and many of them have overloads. Your above examples reflect on classes which is more straight forward but the functions (signatures + implementation) I'm working on are all exported separately using ES module (all located at the same file). I followed the code available in #48 but it only prints the first signature (overload) of the function and I have no idea how to modify it adequately to handle that case. For instance, supposing I'm trying to reflecting on the following function (filter) of the RxJS library (one of my fav libs); I can only get the first signature listed in that file using the code of #48. Any ideas on how to properly handle this case or it is something still to be implemented/enhanced in the tst-reflect lib? I thought about trying to gather those signatures in some way/object to then get the overloads' infos but I have no clue how to proceed.

Thanks!

Hookyns commented 2 years ago

it only prints the first signature (overload) of the function

Hello @carloszimm, I have to change the Type.function: FunctionInfo to something like Type.getSignatures(): ReadonlyArray<FunctionInfo>.

FYI @avin-kavish

Hookyns commented 2 years ago

I just published tst-reflect-transformer@0.12.0 and tst-reflect@0.12.0 with fixed method overloads and added function overloads.

Hookyns commented 2 years ago

@all-contributors please add @carloszimm for ideas and bug report

allcontributors[bot] commented 2 years ago

@Hookyns

I've put up a pull request to add @carloszimm! :tada: