tannerntannern / ts-mixer

A small TypeScript library that provides tolerable Mixin functionality.
MIT License
379 stars 27 forks source link

[QUESTION or BUG] TypeError: (0 , _1.<insert function here>) is not a function #51

Closed Juknum closed 2 years ago

Juknum commented 2 years ago

Hi, I've just discovered your library (and it seems to be awesome) but I'm encountering a weird error:

TypeError: (0 , _1.withC) is not a function

While executing the following:

import { Mixin } from 'ts-mixer';

const withC = (T: B | D) => class extends (T instanceof B ? B : D) {
  // some code here that should inherit B or D classes
}

class A extends Mixin(B, withC(new B())) {
  //                     ^
  //                TypeError: (0 , _1.withC) is not a function
}

Is there anything related to your library? Or I presume I'm doing something wrong, but I'm not experienced enough to see what I do wrong aha :/

tannerntannern commented 2 years ago

Hi @Juknum, I can't really tell what you're trying to do from the code sample, but ts-mixer is designed to mix plain old classes. Using both the function-that-returns-a-class pattern and ts-mixer seems like a strange choice to me, at first glance.

It looks like you have a number of classes: A, B, C(?) and D. What are you trying to accomplish? How do you want these classes to relate to one another?

Juknum commented 2 years ago

The basic idea was to extend B into A using methods from a "generic" class (where methods are applied to another class too).

Another example:

I've modified the letters to make more sense


// ExtA & ExtB are two extended class that depends on a "generic" class 
// where it implies the inherited class Type (either A or B) in some methods of it
class ExtA extends Mixin(A, choose(new A())) {}
class ExtB extends Mixin(B, choose(new B())) {}

// the anonymous class that should be constructed around the class that will be extended const choose = (T: A | B) => class _ extends (T instanceof A ? A : B) { someExtMethod(param: Paramaters<T["someMethod"]>) { return super.someMethod(param); // the supered (this word exist?) method exists in both A and B classes } }


> I know that I can use a classic class for each extension, but it's "easier" to write everything in the same "generic" class since all methods are in common (_code duplication go brr_)

If you know a better way to implement that kind of stuff I'm all ears aha :p
Juknum commented 2 years ago

I've committed my changes to my project, you can see them with the commit above, files are within src/overrides/discordJS/slashCommandBuilders/

tannerntannern commented 2 years ago

I'm still struggling to understand what you're trying to do. Frankly, I don't see a reason to use ts-mixer at all in this situation if you wish to use the function-that-returns-a-class pattern (that ts-mixer was designed to avoid). For example, ExtA doesn't need to mix both A and choose(new A()) if choose(new A()) already has A in its hierarchy.

method exists in both A and B classes ... I know that I can use a classic class for each extension, but it's "easier" to write everything in the same "generic" class since all methods are in common (code duplication go brr)

If both A and B have some of the same functions then I'm not following why those functions couldn't be captured in an interface or abstract class that both A and B inherit from.

Respectfully, I don't have time to advise how you design your code. It is up to you to decide whether the mixin pattern is appropriate for your situation. If you have an issue with ts-mixer specifically, that's when I'm happy to help. It doesn't appear that the original code snippet you supplied gives the error you claimed, nor is it clear that ts-mixer is even the appropriate tool for your situation.

Juknum commented 2 years ago

Yup you're totally right, I was struggling and had to rethink everything, finally, I'm still using your library aha (it's much simpler with it, thanks)