Declaring multi-type properties

Topics: Language Specification
Jun 21, 2013 at 9:57 PM
Looking at BackboneJS (and some other large libraries as well), it uses some conventions where a single property may be of two different types. Most properties may be either of type X or a function that returns X, or sometimes a constructor of X.

For example, Model.urlRoot may be a string, or a function that returns that string. Collection.Model may be a model class itself or a function that constructs a model of that type.

Currently, all those properties must be mapped as "any", as there is no way to replace them for something more meaninful for error checking.

It seems that interfaces partially support this where you can use them to declare a function signature, but it only works for a single one. There is no way to declare a list of possible functions or constructors or types.

Something like:
interface CollectionModel<T> {
    (): T;
class Collection<T> {
    model : CollectionModel<T>;

interface ModelUrlRoot {
    (): string;
class Model {
    urlRoot: ModelUrlRoot;

// or even 

class Model {
    urlRoot: { string; (): string; }
Of course that this could only be used in declarations, but would be great to improve error checking.

Are there any plans to support some kind of "property overloading" like this?
Jun 24, 2013 at 4:16 PM
We've talked about union types, like being able to say number|string, a few times on the forums, though I can't seem to find the threads at the moment.

It turns out that allowing disjunction adds some complication to the type system. On the type inference side, you may get into cases where you infer union types the user didn't intend, making for potentially unreadable error messages. Also, if a union type is used as the type of a function parameter, like below:
function useX(x: number|string) {
  return x;
If the user then hits '.' after the x, what would the autocomplete list contain? Only members common to both number and string (probably won't have many in this case), members of both number and string (nothing would be able to do all from both). It's not straight-forward, and would require some more syntactic and type system support to get to a usable state.

Instead, we opted to keep things simple by just going to 'any' instead. In the future, as the type system matures, we can re-explore the areas we just go to 'any' now.