COMMUNITY

Shorthand syntax for untyped objects?

Everytime I want to define an untyped object (like Object in AS3/JS) I need to use Map<String, Dynamic>. Is there a shorthand syntax for this?

I tried defining an import as follows but that fails with Error: Unexpected <

 import Map<String, Dynamic> as Object;

And Arrays of Objects are a whole new level of tedious:

var items:Array<Map<String, Dynamic>> = new Array<Map<String, Dynamic>>();

Help!

You can use flash.utils.Object from haxe std.

If you want Map<String, Dynamic> instead of Dynamic (which is what flash.utils.Object seems to be), you can do this:

typedef Object = Map<String, Dynamic>;

As for arrays, you don’t need to specify the type on both sides, the other one is inferred:

var items:Array<Map<String, Dynamic>> = new Array();
// or
var items:Array<Map<String, Dynamic>> = [];

// or, with the above typedef
var items:Array<Object> = [];
2 Likes

Omg typedefs. Thank you!!

The array syntax is also super helpful.

One more question. If I create a Map<String, Dynamic> will it automatically map to Dictionary<string, object> in C# and Object in AS3 or will it use some weird-ass custom defined Haxe type?

That is implementation detail and generally should not be relied on.

Hmmm. With C# as a target my Array<Object> has turned into global::Array<object> instead of List<Dictionary<string, object>>.

Strangely enough, individual object variables declared with Object have turned into a global::haxe.ds.StringMap. Why all the confusion? Why doesn’t haxe just use one type for both?

As alternative to Map<String, Dynamic> there is also haxe.DynamicAccess, see https://haxe.org/manual/types-dynamic-access.html and try it here https://try.haxe.org/#c23B6


More an advice than answer, but in general it’s better to avoid mixing types like you do with Map<String,Dynamic>. This is because you lose the advantages of type checking. You don’t want to lose this because the code will be more error prone, and Haxe cannot help you with that. Most things you resolve with “Object” can also be solved in a more type-safe way, which could also results in better performance.

Example. Let’s say you have this:

var map:Map<String, Dynamic> = ["key1" => 123, "key2" => "hello"];

and then do trace(map["key1"].toLowerCase()) that results in a runtime error. It is of course possible to "solve this with if(Std.is(map["key1"], String) but that will add all sorts of runtime type-checking in your code. If you look it at this way; you are replacing what the Haxe compiler should do for you, with some own checks. Ideally you strive for compile time errors to solve things before they are even executed.

Hope this somehow helps.

1 Like

That is because of the incompatibilities between the haxe’s type system and c#'s. Type parameters in Haxe are converted to the generic object type in c#.

1 Like

Of course, Mark. I always prefer using strongly typed data wherever possible. However this is an edge case where I’m working with JSON so I need the flexibility of JS objects aka Dictionary<string, object>>.

Also thanks for introducing DynamicAccess, that’s a new one.

1 Like

By the way, have you checked tink_json?

1 Like