Trident D'Gao
Trident D'Gao

Reputation: 19742

What's the use of union types in TypeScript?

First off, there are no official guidelines (AFAIK as of March 8, 2015) on using this new feature of TypeScript called the union types. Well, I tried to find a way of using them myself. It hasn't been easy. I am still struggling to find a place for union types in my code:

What is left?

Am I right that those 2 are the only valid ways of consuming union types in TypeScript at the moment?

If so, are there any plans to extend their applicability?

If no, what am I missing out?

Upvotes: 3

Views: 790

Answers (1)

Daniel Rosenwasser
Daniel Rosenwasser

Reputation: 23463

I don't think you can get a single answer for this; at the very least, union types handle many different use cases that enable users to write TypeScript in a manner similar to how they might write canonical JavaScript. Here's an attempt to explain anyway.

When you have two types that are structurally (and ideally functionally) similar, one benefit is that you can use the intersection of properties that they share as a point of abstraction.

In the cases where you have two types that are not structurally similar, but have parallels in how they their information can be treated, it can be useful for making a function for normalizing that information into a common abstracted form.

As an example, ES6 tagged templates are very similar to call expressions:

f `hello ${ 123 } ${ 456 } world!`

The above tagged template desugars to something similar to the following:

var _t = ["hello ", " ", " world!"];
_t.raw = ["hello ", " ", " world!"];
f(_t, 123, 456);

You could imagine that in a compiler, it would be ideal if they could be treated equally to call expressions when convenient, but handled specially when the two are distinct enough. Let's try to model this:

interface TemplateExpression extends Expression {
    // ...
}

interface TaggedTemplateExpression extends Expression{
    callTarget: Expression;
    template: TemplateExpression;
}

interface CallExpression extends Expression {
    callTarget: Expression;
    arguments: Expression[];
}

type CallLikeExpression = CallExpression | TaggedTemplateExpression;

function getEffectiveCallArguments(expr: CallLikeExpression): Expression[] {
    if (expr.kind === SyntaxKind.CallExpression {
        // ...
    }
    else {
        // ...
    }

    // OR, if you don't want to have a tag,
    // you could check expr's properties
    if ((<CallExpression>expr).arguments) {
        // treat as CallExpression
    }
    else {
        // treat as TaggedTemplateExpression
    }
}

Both CallExpression and TaggedTemplateExpression have a callTarget in common, so you can always get the expression being invoked from a CallLikeExpression by just using the callTarget property.

If you'd like to get the arguments that will be fed into call, you can extract it using getEffectiveCallArguments which is aware of how do deal with the differences between the two.

Upvotes: 2

Related Questions