BAM Weblog

Roy - Type Aliases

Brian McKenna — 2011-10-23

Roy now has a form of type aliasing. You can give names to types, like so:

type Name = String
type Animal = {name: Name, legs: Number}
let zebra: Animal = {name: "Zebra", legs: 4}

The benefits are mainly for structural types:

  1. You don’t have to type out a long structure whenever you want to be explicit
  2. Better error messages

For example, this is a poorly typed program without an alias:

let getName x = x.firstName ++ x.lastName
console.log (getName {})

And this is the error message:

Type error: {} is not {firstName: String, lastName: String}

You can imagine the error would be kind of scary if the structure was heavily nested or had more than just a couple of elements.

This is a poorly typed program with an alias:

type Person = {firstName: String, lastName: String}
let getName (x: Person) = x.firstName ++ x.lastName
console.log (getName {})

And this is the nicer error message:

Type error: {} is not Person

I originally wanted inference to use the scope to check which aliases it could satisfy and use the most appropriate:

type Person = {firstName: String, lastName: String}
// `x` is inferred to be Person from the scope
let getName x = x.firstName ++ x.lastName

Which is something that Yeti is able to do. Instead, I implemented a very simple version that will just propogate explicit aliases. Using the simple version might conflict with my future plans.

Later on I hope to be able to use the type aliases to output nicer JavaScript:

 // Roy: type Person = {firstName: String, lastName: String}
 var Person = function(firstName, lastName) {
     this.firstName = firstName;
     this.lastName = lastName;
 };

And I might even be able to extend aliases to output information about the hierarchy:

// Hypothetical Roy: type Employee = Person with {wage: Number}
var Employee = function(firstName, lastName, wage) {
    Person.call(this, firstName, lastName);
    this.wage = wage;
};
// Just for documentation:
Employee.prototype = new Person();

But maybe not. I’ll have to try it out.

In adding aliases, I fixed something that I wanted to do for a while; using structural types for normal type annotations:

let getName (x: {name: String}) = x.name
console.log (getName {name: "TEST"})

Let me know what you think.

Please enable JavaScript to view the comments powered by Disqus.