You could use an abstract to augment the push function. Also you will need to make sure the compiler sees the start and duration field as floats, so it can pass the constraint check.
class Test {
static function main(){
var arr:ActionOptionsArray = [];
arr.push({start: 0., duration: 1.});
arr.push({start: 2., duration: 4., test: 1});
}
}
@:forward
abstract ActionOptionsArray(Array<ActionOptions>) from Array<ActionOptions> to Array<ActionOptions>{
public inline function push<T:ActionOptions>(v:T)
return this.push(v);
}
typedef ActionOptions = {
var start:Float;
var duration:Float;
}
typedef SecondActionOptions = {
> ActionOptions,
var test:Int;
}
Just to clarify. The method proposed by Justin is definitely preferable, but is limited: you have to know all the optional fields ahead of time and define them accordingly. As opposed to that, Kevin’s solution allows arbitrary extra fields, for the cost of relying on abstracts and constrained type parameters.
class Test {
static public function main() {
var arr : Array<ActionOptions> = [];
arr.push(new ActionOptions(0, 1));
arr.push(new SecondActionOptions(2, 4, 1));
}
}
class ActionOptions {
public function new(start : Float, duration : Float) {
this.start = start;
this.duration = duration;
}
public var start(default, null) : Float;
public var duration(default, null) : Float;
}
class SecondActionOptions extends ActionOptions {
public function new(start : Float, duration : Float, test : Int) {
super(start, duration);
this.test = test;
}
public var test(default, null) : Int;
}
It actually seems that the Haxe type system does not see structure extensions as sub-types the way sub-classes are seen.