JavaScript Type Inference

Note: This page is based on a page on the Boo wiki about Type Inference

Unity's JavaScript can be used as a statically typed language.

Static typing is about the ability to type check a program for type correctness.

Static typing is about being able to deliver better runtime performance.

Static typing is not about putting the burden of declaring types on the programmer as most mainstream languages do.

The mechanism that frees the programmer from having to babysit the compiler is called type inference.

Type inference means you don't have to worry about declaring types everywhere just to make the compiler happy. Type inference means you can be productive without giving up the safety net of the type system nor sacrificing performance.

The type inference kicks in for newly declared variables and fields, properties, arrays, for statement variables, overriden methods, method return types and generators.

Variables
The var keyword is used to create new variables in the current scope. When assigning an initial value, the type for the new variable will be inferred from the expression on the right.

Only the first assignment to a variable is taken into account by the type inference mechanism. The following program is illegal:

Fields
Declare the new field _name and initialize it with an empty string. The type of the field will be string.

Arrays
Note: this does probably not apply to javascript as the [] create lists and not arrays...

The type of an array is inferred as the least generic type that could safely hold all of its enclosing elements.

For statement variables
Note: this does probably not apply to javascript as the [] create lists and not arrays...

This works even when with *unpacking*:

Overriden methods
When overriding a method is not necessary to declare its return type since it can be safely inferred from its super method.

Note: the current version of Unity JavaScript does not implement the override keyword

Method return types
The return type of a method will the most generic type among the types of the expressions used in return statements.

When a method does not declare a return type and includes no return statements it will be typed System.Void.

(!) A Word of Caution About Interfaces
When implementing interfaces it's important to explicitliy declare the signature of a method, property or event. The compiler will look only for exact matches.

In the example below the class will be considered abstract since it does not provide an implementation with the correct signature:

(i) Ok. So where I do have to declare types then?
Let's say when.

The above code will still run without the explicit types in the examples above, but it will revert to dynamic type checking, which is slower.
 * When the compiler as it exists today can't do it for you. Ex: parameter types, recursive and mutually recursive method/property/field definitions, return for abstract and interface methods, for in untyped containers, properties with a only set defined


 * When you don't want to express what the compiler thinks you do:


 * When you want to access a member not exposed by the type assigned to an expression without resorting to dynamic typing:

Dynamic Type Checking
Sometimes the type inference does not have enough information to infer the correct type. In that case the type will be set to object and all further type checking on the variable will be done in runtime as opposed to compile time. This is also called duck typing. An example of where type inference fails is the return value of GetComponent. As the type of the return value depends on the input parameter, it is not possible to know beforehand what type it will be.

There are two reasons why one wants to avoid dynamic type checking:


 * Performance: Run-time type checking takes a bit of processing time, expecially in code that gets run over and over. Statically typed variables (manually typed or through type inference) take a bit less time to run.


 * Better error reporting: Say you have the following code:
 * Despite the fact that "wroldRotationAxis" is meaningless, Unity will not know this until this code actually gets executed at runtime. If pa had been specifically typed as a ParticleEmitter, the compiler would tell you that wroldRotationAxis was not a member of ParticleEmitter.


 * This is doubly important with code that gets run only sparingly, such as end-of-level code. If your level takes 5 minutes to complete, and there is a typo in your end-of-level script, then not statically typing your variable will have just cost you at least 5 minutes.

One can also explicitly enable dynamic type checking, or duck typing by setting the variable type to object:

Even though this seems odd and counter intuitive, this is useful for a lot of dynamic tricks. See Category:IQuackFu for more information.