Haxe is great for when you want to write an entire application in Haxe, then transpile to multiple targets, and then care about the target platform only to the extent that you want your application to just work.

The various haxe game engines are a good example of this kind of use case, where they transpile your haxe code to C++ or JavaScript and then your transpiled code combines with JavaScript code that the game engine provides or with C++ code that the game engine provides and the result is that everything "just works", both natively and in the browser.

I also have high hopes for this approach in relation to GUI programming (HaxeUI, FeathersUI, etc. are very interesting).

But my usecase was different: I wanted to make an API for my business logic that would transpile to Python, JavaScript and Java, and give a developer on each target platform a native look and feel, as if they were interacting with a native Python API or Java API, etc.

Basically, when you do that, you'll discover that Haxe is too much of a leaky abstraction.

For example when your API requires passing an iterator over Strings or returns an iterator over Strings, you'll discover that this doesn't automagically turn into java.util.Iterator<String> when you transpile to Java. Rather Haxe has its own implementation (haxe.Iterator) that transpiles to some weird Java object that a Java developer will have a difficult time interacting with. ...this is true not just for iterators but for a lot of very basic things like collections, exceptions, etc.

Haxe does expose target-specific things on the Haxe-side, so you can write Haxe code that will accept java.util.Iterator or return java.util.Iterator, but, obviously, java.util.Iterator will not be available when you try to transpile to something other than Java. So whenever you want to just use an iterator, your code is going to be full of "if this platform then behave like x, if that platform then behave like y, ..."

Outside of development around the main Haxe-based game engines, you'll also find that the community is just too thin to properly maintain libraries. For example, several libraries that implement very basic things haven't been touched in years and I discovered that the HashMap implementation in the Haxe standard library is just broken and no one seems to care or notice. It just doesn't handle collisions [1]. ...the only way I can explain that to myself is by assuming that there just aren't enough people using HashMaps on Haxe directly, because the game engines or target platforms provide something else that displaces that functionality or that games are just the kinds of applications where the errors that result from hash collisions aren't noticeable. The advice I got from a seasoned Haxe veteran regarding libraries was to not use haxelib and dependencies at all but instead copy & paste the library code I really needed, fighting hard to keep that to a minimum, and maintain it myself.

It's a pity, because the Haxe language is great, and the ideas behind the architecture are great, but the current implementation IMO just hasn't yet made enough progress on the journey it embarked upon for Haxe to be an option yet for major investments in any non-game software development.

[1] https://github.com/HaxeFoundation/haxe/blob/development/std/...