« ECMAScript 4th edition Reference Implementation M2 | Main | ECMAScript 4th Edition Vectors Proposal Draft 1 »

Type Parameters in ECMAScript 4th Edition

The ECMAScript 4th Edition draft specification includes something called type parameters, also known as parameterized types or generics. This feature is useful for adding type checking to collection classes. For example, let's say you have a List class that you have customized to your liking.

You like it so much, in fact, that you use it in many different situations. The only problem is that in ActionScript 3.0, you can't easily use strong typing to specify that a specific instance of List should contain only a certain data type. You could extend List, I supppose, and create a ListOfIntegers class, a ListOfStrings class, etc., but that can get hard to manage if you use it for more than just a few different types.

The type parameters feature, however, makes strong typing of collections much easier. If you saw my previous post about Vectors, you've already seen type parameters in action because the Vector class requires them. But let's rewrite the List class using a type parameter:

What we've done is define List such that it is now a "list of some type", where the type is represented by the parameter "T". In other words, the class List.<T> is "generic" in the sense that it is not tied down to a specific data type, at least until you specify a type when you create an instance of the class. This means that we can use the parameter "T" inside our class definition as if it were a type. You can see in the declaration of the variable head that we used a type annotation of "T". When we later create an instance of the List.<T> class, the compiler will substitute the type we specify for every occurrence of "T".

Let's say I have a class called Employee and I want to create an instance of my List class that stores only instances of the Employee class. Here's what it would look like:

So you're probably wondering what's up with the funny syntax for type parameters. How did we end up with the syntax className.<Type> for type parameters? Well, the working group went through a long discussion about it, which you can read on the type parameters proposal discussion page at the ecmascript.org site.

ES4 Type Parameters are Unbounded

One thing you may have noticed about the List.<T> class is that T can be any type. We passed in the type "Employee", but we could have passed in int, string, or any other built-in or custom type. There's no way in ES4 to limit, or in other words create bounds for, the types that you can pass in to for "T". Some languages with generics allow you to constrain the type parameter by setting up type boundaries. In other words, some languages allow you to specify a restricted set of types that can be used as typed arguments. For example, in Java you can define a class that takes a type parameter that must extend another class, so you could say class List<T extends Employee>, to get a List class that takes only subclasses of Employee. The ES4 spec does not require implementations to provide bounded type parameters.

ES4 Type Parameters are Invariant

Best way to explain this is through an example. Let's take that Employee class we talked about earlier and extend it with a new subclass called TechWriter. Clearly, TechWriter is a subclass of Employee, and can be safely used anywhere that Employee is used. But does that mean that List.<TechWriter> is a subtype of List.<Employee>? It turns out the answer is no. The ramifications of this can be seen in the following example, in which the function reprimand() takes a parameterized List as its parameter:

Calling the reprimand() function with a value of type List.<TechWriter> causes an error because the function is expecting the type List.<Employee>. Other languages use something called variance annotations to solve this problem. In this case, the error would go away if the subtype relationship of the two lists matched the subtype relationship of the types Employee and TechWriter. Such variance is called covariance. Java, for example, allows you to use wildcards to indicate that you want to allow covariance, something like <? extends Employee> would do it if you used that in the declaration of reprimand().

The type parameters proposal does leave open the possibility that variance annotations could be added in a later edition of ECMAScript. The proposal points to a journal article that proposes a variance annotation style that is simpler than Java's. If ECMAScript goes that route, you would be able to rewrite the function to support covariant type parameters with just one extra symbol (note the + symbol in the declaration of reprimand()):

Personally, I like the brevity of this style of variance annotation and hope that they adopt this for ECMAScript 5. The proposal lists a workaround, however, that purportedly mitigates the need for variance annotations. I have to say, though, that the proposed alternative is little intense for my taste, but hey, I'm just a tech writer. You can have a look at it and see if you like it better than using a variance annotation. Look for the code example that defines a class called Container.<T> on the type parameters proposal page under the section titled Variance Roadmap.

Here are some useful links I came across in researching type parameters. These deal mostly with generics in Java, C++ and C#:

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)