Is there a way to alias types in Haxe when compiling to JavaScript?

I have the following two classes:

package geometer;

class Vector2Impl {
  public var x: Float;
  public var y: Float;

  ... operations and methods...
package geometer;

@:forward(x, y)
abstract Vector2(Vector2Impl) from Vector2Impl to Vector2Impl {
  public
  function new(x: Float, y: Float) {
    this = new Vector2Impl(x, y);
  }

  ... operator overloads ...
}

I did this so I could overload operators in Vector2. This all works fine from inside of Haxe, however, we compile from Haxe to JavaScript. Our output JavaScript is then used in mocha tests.

Unfortunately, classes declared abstract are completely omitted from the JS code (well, this isn't entirely true, but they do look something like:

var geometer__$Vector2_Vector2_$Impl_$ = {};
geometer__$Vector2_Vector2_$Impl_$.__name__ = true;
geometer__$Vector2_Vector2_$Impl_$._new = function(x,y) {
    return new geometer_Vector2Impl(x,y);
};

So, in my tests, instead of using Vector2, I am forced to use Vector2Impl. This is a bit of a pain, because a) it requires more typing, and b) it exposes an inconsistent interface between Haxe clients and JavaScript clients. I could deal with it, but since Haxe isn't completely compiling out the type Vector2, I'm wondering if there is a way I can alias Vector2Impl to Vector2 inside of the generated .js file. That way, instead of doing the following in my tests:

'use strict';

let expect = require('chai').expect;
let library = require('../../dist/library.js');
let geometer = library.geometer;

// Unfortunately, abstract classes (Vector2) are not available in JS-land.
let Vector2Impl = geometer.Vector2Impl;

require('../nyc-reporter');

describe('Vector2Impl', function() {
  describe ('#new', function() {
    it ('should create a new Vector2Impl object', function() {
      let v = new Vector2Impl(20.5, 100.0);

      expect(v.x).to.eq(20.5);
      expect(v.y).to.eq(100.0);
    });
  });
});

I could do this:

'use strict';

let expect = require('chai').expect;
let library = require('../../dist/library.js');
let geometer = library.geometer;

// Unfortunately, abstract classes (Vector2) are not available in JS-land.
let Vector2 = geometer.Vector2;

require('../nyc-reporter');

describe('Vector2', function() {
  describe ('#new', function() {
    it ('should create a new Vector2 object', function() {
      let v = new Vector2(20.5, 100.0);

      expect(v.x).to.eq(20.5);
      expect(v.y).to.eq(100.0);
    });
  });
});

Obviously, I know that I can't use the operator overloads in JavaScript, since the language doesn't support it, but if I could use all the other methods available in Vector2Impl by calling it Vector2, that would be awesome.

NOTE: I know I could just do this:

let Vector2 = geometer.Vector2Impl;

But, I'd rather the client not even be aware of the Vector2Impl class, if possible.

Answers:

Answer

You could simply annotate Vector2DImpl with @:expose metadata:

@:expose("geometer.Vector2D")
class Vector2Impl {
    ...
}

This includes it in $hx_exports as geometer.Vector2D.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.