I believe the reason for that is the multi-type nature of Map.
What this allows is for Map<String, T> to always become
haxe.ds.StringMap and not my.custom.StringMap. This in turn means that
most of the time the abstraction comes at no overhead, because it is
substituted for the concrete class and thus further optimization like
inlining will work.
If you want to write code against something as generic as IMap, you
will have to write it against IMap explicitly.
Or you can use @:generic, that should also work. It's trading away the
overhead of IMap against the overhead of implementation for different
value types (even though not necessary).
Regards,
Juraj