04. Types and type inference in Haxe

2014-09-05

Haxe type system

Haxe, like many OOP languages, is strictly typed. This means that every object needs to have a type. The Haxe compiler will warn you about type related errors before you even run your program.

In this tutorial we'll learn about the type system in Haxe, as well as type inference that Haxe employs.

When a variable is declared, its type is specified after its name.

var myText:String;

There are three basic types in Haxe - Bool, Int and Float.

Bool, also known as boolean, has 2 possible values - true and false.

var flag:Bool = true;

An Int is an integral number.

var num:Int = 120;

It is also possible to use the hexadecimal format with Int type:

var red:Int = 0xff0000;

The Float type is used for storing floating point numbers:

var pi:Float = 3.14;

The compiler will throw an error on compilation if it finds any type mismatches. For example, assigning a String value to an Int is illegal and will not compile. In case you need to create a variable that can accept any value, there's Dynamic type for that. Note that its use is not recommended and you should only use Dynamic type when absolutely necessary.

var v:Dynamic = 3.14;

v = "Text";

Types should also be specified for elements of Arrays and Vectors, like so:

var numbers:Array<Int> = [1, 2, 3, 4, 5];

var text:Array<String> = ["Hello", "world"];

If you want to use differently typed values in Arrays of Vectors, you can use the Dynamic type:

var d:Array<Dynamic> = [1, 2, 3, "Hello", "world"];

Multi dimensional arrays are declared like this:

var arr:Array<Array<Int>> = [[1, 2, 3],[1, 2, 3],[1, 2, 3]];

Even though Haxe is a strictly typed language, the compiler has type inference, which means that actually writing the type is optional.

When a variable is declared without a type, it receives the Unknown type, until the compiler finds the first line that directly sets a value to that variable and automatically assigns the type. The type can not be changed after that.

For example, these two lines are both legal:

var myVar:String = "Text";

var myOtherVar = "Text";

The reason is that the compiler sees the "Text" value being assigned as the value, sees that the value is a String value, and figures out to set the type of the variable to String.

This can also be done with any class:

var myCustomThing = new CustomThing();

An example of an declaring a variable without a type, and assigning a value after that:

var myVar;

myVar = "text";

At this point myVar's type is set to String by the compiler and can not be changed.

Watch out for errors like this:

var myVar;

myVar = 10;

myVar = "hello";

The compiler will throw an error, because the type of the variable is set to Int when the number is assigned as its value, and remains Int when you try to assign a string value to it. Since we can't assign a String value to an Int variable, there's a type mismatch.

Type inference also applies to function parameters:

function myFunction(param: Int)

{

}

Function with an untyped parameter would look like this:

function myFunction(param)

{

}

In this case, the type is set according to what is sent to the function first.

Here, the parameter type is set to Int:

myFunction(100);

And in this case it's set to String:

myFunction("Hello");

Again, if the parameter type was already set once, all following calls need to use that parameter type.

Although type inference is a convenient feature to have and will often speed up the coding, it is still a good idea to always type your variables, at least for the sake of code readability.

Now that we have a basic knowledge of the type system in Haxe, let's move on to learn about the loops and iterators in Haxe.