Type Annotations Primer
To put it simply, when you declare a function or variable, a type annotation lets you specify it's type. So let's say you have a variable representing the owner:
var owner = self.getOwner();
there's a few things you might noticed, for example, if the owner is a player, assist or projectile, you aren't getting any specific api functions for it when completing on owner
, this is because FrayTools can't tell what type it is. so to get around that, you will have:
For a Character:
var owner:Character = self.getOwner();
For a Projectile:
var owner:Projectile = self.getOwner();
For an Assist:
var owner:Assist = self.getOwner();
and so on, doing this allows you get get more accurate completions on your variables when using FrayTools, this becomes especially important when using makeObject
which returns the Any type or makeArray
.
Of course, type annotations don't actually change how your code functions, but it does help with readability and improves the coding experience in the long run as code gets larger or if you take a break from a project.
For stuff like strings, numbers and booleans we have: String
, Int
, Float
and Bool
Array Types
For Arrays look a bit different, you have an array type being Array
but you also have to include what the array items are so:
For an array of Ints:
var arr:Array<Int>: [];
Array of Strings
var arr:Array<String> = [];
Array of Characters:
var arr:Array<Character> = [];
This also works for 2d Arrays like so:
var arr:Array<Array<Int>> = [[]];
Structure Types
In addition to arrays you can also write types for structures.
So lets say you had a function called magic()
that returned
{
greeting: "Hey guys",
greeter: self
}
it's type would be:
{
greeting: String
greeter: Character
}
assuming its called from a character script
and with variable assignment:
var greeterObject: {greeting: String, greeter:Character} = {greeting: "Hey guys", greeter: self};
of course this can be useful in other ways too, for example if you wanted to store a player and a given filter together you could simply do:
var glowFilter:GlowFilter = new GlowFilter();
var player:Character = match.getPlayers()[0]:
var combined: {player:Character, glow: GlowFilter} = {player: player, glow: glowFilter};
// adding the filter later
combined.player.addFilter(combined.glow);
Composing Types
You can also compose types, for example lets say you wanted an array of objects, with each object having one field for a player, another for a filter you can have:
var playersWithFilters:Array<{player:Character, glowFilter: GlowFilter}> = [];
Let's say we wanted our type to also store an array of Ints, just because:
var playersWithFilters:Array<{player:Character, glowFilter: GlowFilter, numbers: Array<Int>}> = [];
Or if we wanted another field, maybe an a boolean field to say if the filter was applied:
var playersWithFilters:Array<{player:Character, glowFilter: GlowFilter, numbers: Array<Int>, filterApplied: Bool}> = [];
and of course we can split it over multiple lines:
var playersWithFilters:Array<{
player:Character,
glowFilter: GlowFilter,
numbers: Array<Int>,
filterApplied: Bool
}> = [];
The nice thing about these is that you get autocomplete on the types inside the types as well, regardless of whether you hae a 1D array or a 400D array or an array of objects or an object containing arrays, or objects containing objects etc.
Function Types
You can also add type annotations to function arguments as well as the function return types
So if you want to annotate a function that expects a string you have:
function greeting(message:String) {
Engine.log(message);
}
but if say, you wanted to specify return types as well(FrayTools and automatically infer this most of the time for functions you define)
function makeGreeting(name:String): String {
return "Hey Guys its " + name;
}
and if you wanted to have more complex types, those work as well here, just ensure the return type fits
function removeFilter(filterObj: {player:Character, filter:GlowFilter, filterApplied: Bool}): {player:Character, removedFilter:Bool} {
var player = filterObj.player; // Because we specified the type above, FrayTools can infer it for us
var filter:GlowFilter = filterObj.filter; // You can also just put the type anyways
player.removeFilter()
return {
player: player,
removedFilter: true
};
}
Function types can also be especially helpful when working with event listeners, for instance:
self.addEventListener(GameObjectEvent.HIT_DEALT, function (event) {
Engine.log(event.data.foe);
});
would have zero code completion on event.data, because we haven't specified the type, but if we have a type signature:
self.addEventListener(GameObjectEvent.HIT_DEALT, function (event:GameObjectEvent) {
Engine.log(event.data.foe);
});
It will autocomplete for all the fields under event.data.