Create instance of type T

I am trying to create an instance of a generic type in Haxe, and I am having trouble finding a solution. I have searched online for a solution, but most results seem to be C# related. Filtering out the C# results does not get me to where I need to go.

I currently have the following code:

data.defaultPos = defaultPos == null ? Type.createInstance(Type.getClass(T), [0, 0]) : defaultPos;
data.defaultSize = defaultSize == null ? Type.createInstance(Type.getClass(T), [100, 100]) : defaultSize;

I am getting the following error when using the above code: Type parameter T is only available at compilation and is not a runtime value.

In C#, the same can be done using this code:

data.defaultPos = defaultPos == null ? Activator.createInstance(typeof(T), [0, 0]) : defaultPos;
data.defaultSize = defaultSize == null ? Activator.createInstance(typeof(T), [100, 100]) : defaultSize;

But an equivalent in Haxe seems difficult to find, if at all. Is it possible to do this in Haxe?

I believe Haxe will allow you to do new T (), but not to use Type.getClass (T)

I forget if new T () requires the class to be @:generic or not

Okay, I wasn’t able to do it at the time since my computer crashed and have spent the last two hours trying to resolve the issue. But I’m finally back.

I tried the above, and I’m now getting a different error: vm.VectorMap.T does not have a constructor. This is using @:generic at the top of the class. Without it, I get Only generic type parameters can be constructed., which is a bit odd because you would think by adding the tag that it would remove that error.

EDIT Here is the full error on compile:

../vm/VectorMap.hx:20: characters 47-58 : vm.VectorMap.T does not have a constructor
../vm/VectorMap.hx:20: characters 47-58 : Void should be Dynamic

Ah, I finally managed to figure it out. I realised that generic types can’t be instantiated, but classes in Haxe such as sys.db.Manager uses the Class<T> parameter in the constructor for you to pass the type as a reference to itself.

So my solution:

@:generic
class VectorMap<T>
{

    public function new(type:Class<T>)
    {
        _typeInstance = type;
        _types = new Map<Int, Dynamic>();
        _drawList = [];
    }

    ...

    public function registerType(value:Int, method:Int, ?defaultPos:T, ?defaultSize:T, ?properties:Dynamic)
    {
        var data:Dynamic = {};
        data.defaultPos = defaultPos == null ? Type.createInstance(_typeInstance, [0, 0]) : defaultPos;
        data.defaultSize = defaultSize == null ? Type.createInstance(_typeInstance, [100, 100]) : defaultSize;

    }

}

Instead of taking an argument of type Class<T>, take an argument of type Float -> Float -> T.

class VectorMap<T>
{

    public function new(constructor:Float -> Float -> T)
    {
        _constructor = constructor;
        _types = new Map<Int, Dynamic>();
        _drawList = [];
    }

    ...

    public function registerType(value:Int, method:Int, ?defaultPos:T, ?defaultSize:T, ?properties:Dynamic)
    {
        var data:Dynamic = {};
        data.defaultPos = defaultPos == null ? _constructor(0, 0) : defaultPos;
        data.defaultSize = defaultSize == null ? _constructor(100, 100) : defaultSize;

    }

}

Then instead of “new VectorMap(Point),” you use “new VectorMap(Point.new).” This blog post explains the benefits:

2 Likes