tl;dr
Remember to put the brackets
(untyped new JQuery("#images").imageLoader)({});
// ^ ^
// |________these____________________________|
Abstract
Static type system of Haxe helps you a lot by performing type-checking in the compilation phase. You will be notified errors before the application is run.
Since some Haxe targets (e.g.. JS and PHP) are dynamic in nature, many of
the native
libraries/frameworks are also very dynamic. You have to use
the untyped
keyword in Haxe very often to workaround the compiler type-checking.
As a best-practice, to avoid unnecessary suppression of type-checking,
brackets should always be placed in order to constrain affecting slope
when using the untyped
keyword in an expression.
Example: using jQuery plug-in
For illustration, I will explain a frequently faced problem that is how
to use jQuery plug-in in Haxe (following will use jQueryExtern). In
case there is a plug-in that will add a method, .imageLoader(config)
,
to jQuery. But since there is no such method declared in the JQuery
extern class, if you simply compile new JQuery("#images").imageLoader({});
,
it will certainly fail with error “jQuery.JQuery has no field imageLoader“.
You have two options:
- Create a plugin class and then “using” it.
- Use a quick and dirty
untyped
keyword.
For 1, you can refer to some experimental plug-in externs from jQueryExtern. Read my blog post on how to use it with ”using”. This method takes some more amount of coding and does not work well with optional arguments.
For 2, adding a untyped
keyword will shut the complier’s mouth up:
untyped new JQuery("#images").imageLoader({});
.
The above of course works, but you will lose many type-checking in the
expression where are unnecessarily suppressed. e.g.. if you forgot to
define config
in
untyped new JQuery("#images").imageLoader(config);
…it will compile and fails at runtime with “Uncaught ReferenceError: config is not defined“.
Instead, constrain the untyped
scope by placing a pair of brackets:
(untyped new JQuery("#images").imageLoader)(config);
…it now (correctly) fails to be compiled with error “Unknown identifier : config“.
It is useful because sometimes you may code like this:
(untyped new JQuery("#images").imageLoader)({
images: images,
async: 10,
complete: function(e, ui) {
progressbar.progressbar("value" , (++loaded).map(0, numOfFrames, 0, 100));
},
allcomplete: function(e, ui:Array) {
new JQuery(function(){
var playback = new JQuery("#playback").html("");
for (item in ui) {
new JQuery(item.img)
.attr("id", "playback-" + Std.string(item.i))
.appendTo(playback)
.hide();
}
if (displayMode.enumEq(PlaybackMode))
imageLoop(12);
new JQuery("#toggle-play-btn").removeAttr("disabled");
new JQuery("#toggle-slow-btn").removeAttr("disabled");
new JQuery("#main").removeClass("loading");
});
}
});
If you do not place brackets around untyped
(at line 1 as shown
above), you will unnecessarily lose type-checking for over 90% of codes
(begin with line 2 of above), which is pretty bad.