// type annotation for variable: var a : String; // type annotation for function: function zap(x : int, y:Date) : boolean { ... }Type annotations are always optional.
If an operations is illegal according to the type (eg. calling a method or property which doesn't exist for the type, or trying to divide a number by a date), the compiler will issue a warning.
Mascara uses local type inference to try to resolve the type in case it is not provided by an annotation.
var x = 10; // x gets type int because the number 10 is an int var y = x + 2 // y gets type int because int + int always yields int var z = new Date(); // z gets type DateThis means you don't have to annotate everywhere, just places where the compiler can't infer the type.
One place where the type inference can never determine the types, is function parameters. So if you want to annotate as little as possible to get full type checking, then annotate function parameters. Return values however, can usually be inferred if the parameters are annotated.
Type annontations can be one of:
- A class (e.g. the built in types int, String, Date etc. are all classes.)
- A structural type
- A function type
- The *-type (which is short for "anything".)
- Distinct types combined with unions.
A variable (or "slot") can be asssigned a value of a different type, if the the slot has a wider type. A supertype is wider than a subtype, and the *-type is the widest - it can contain any other type.
var a : int = 10;
var b : Number = a; // OK, since Number is wider than int
var c : = b; // OK, since is wider than anything
var d : int = c; // ERROR, since int is narrower than *
The cast operator can be used to explicit change the type of an expression to a narrower type:
var a : Number = 10; var b : int = a cast int;Note however that this may lead to runtime errors if the casted value is not actually the supposed type.