Closed LemonPi closed 4 years ago
Hi @LemonPi, so I believe the functionality you're looking for is custom instanceof
behavior, which is currently listed as a "non-feature" of ts-mixer. The primary reason for this is that in order to define this custom behavior, ts-mixer would have to modify the source classes, which I would really like to avoid.
However, I might be able to add a hasMixin
function to ts-mixer as a replacement for instanceof
. It could also use type guards so that -- to use your example -- the type of entity
would automatically be inferred as Actor
simply by using hasMixin
in the if
statement...
Let me do some digging and I'll get back to you. 🙂
Ah interesting, I didn't know that you could implement custom instanceof
behaviour with Symbol.hasInstance
! And yeah, I think something "softer" would be just fine (it can just a call to a third party function rather than the instanceof
operator).
One solution I can think of is if in the mixin module you have a map of base class to arrays of mixin classes that you populate inside calls to Mixin(...)
. Then the hasMixin
function would just check if that mixin is inside the mapped array.
This map solution you describe is exactly what I'm investigating at the moment. However, it is a little more complicated than just checking the mapped array, because the mixed class may be buried in the prototype chain, and the mixed class's constituents may also have mixed classes buried in their prototype chains.
Hmm things could get expensive with large prototype hierarchies... I'm currently using a heuristic way of checking that all properties of a mixin are in the prototype chain of the object somewhere. I'm not sure how the performance of this compares to prototype finding, but it also requires that I do the casting which is annoying.
Well good news: you won't have to cast anymore because the hasMixin
function already does the type narrowing for you. 5.3.0-beta.0 has been released, and you can try it out today with npm install ts-mixer@5.3.0-beta.0
. The new README section covers it in more detail.
Let me know what you think! If you don't see any issues, I'll promote it to a full release.
Regarding your performance concern, my guess is that walking the prototype chain will be less intensive than checking for all properties, although I have not run the benchmarks to back this up. When you're working with mixins, prototype chains are often not very deep, but instead "wide", meaning the algorithm doesn't have to iterate very far to find what it's looking for. If someone has a very deep prototype chain with many layers of ts-mixer classes within, performance could suffer, but my guess is that it would be slight.
That being said, do let me know if you find the performance to be subpar, and I will see if I can improve my implementation.
Great, seems to work fine! The narrowing conversion removes even more boilerplate (and things that could get out of sync), which was my motivation for using this library in the first place :D. I haven't done any profiling, but I didn't see any dramatic difference in switching so it should be good to go 👍
Glad to hear it works well for you. 5.3.0 is live. Thanks for your interest in ts-mixer and helping improve the library!
Is there a way to check if an object uses a certain mixin (its class is defined with that mixin)? My use case for example would be
I could work around this by checking if the object has a certain function, but I would prefer a more general solution (since this solution would be specific to the methods of each mixin)