TypeScript中的联合类型有什么用?

时间:2015-03-08 20:00:34

标签: typescript

首先,没有关于使用TypeScript的新功能(称为联合类型)的官方指南(截至2015年3月8日的AFAIK)。好吧,我试图找到一种自己使用它们的方法。这并不容易。我仍在努力为我的代码中的联合类型找到一个位置:

还剩下什么?

  • 混合原语(通过typeof解构)
  • 混合类(通过instanceof解构)

我认为那些2是目前在TypeScript中使用联合类型的唯一有效方法吗?

如果是的话,有没有计划延长其适用性?

如果不是,我错过了什么?

1 个答案:

答案 0 :(得分:2)

我不认为你可以得到一个答案;至少,联合类型处理许多不同的用例,使用户能够以类似于编写规范JavaScript的方式编写TypeScript。无论如何,这是试图解释的。

当你有两种结构上(理想情况下)功能相似的类型时,一个好处就是你可以使用它们共享的属性作为抽象点。

如果您有两种类型不相似的类型,但它们的信息可以如何处理,则可以将函数用于将该信息规范化为常见的抽象形式。

例如,ES6标记模板与调用表达式非常相似:

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

以上标记的模板涉及类似于以下内容:

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

你可以想象在编译器中,如果它们在方便的时候可以被同等对待来调用表达式,那么它们将是理想的,但是当两者足够清楚时特别处理它们。让我们尝试对此进行建模:

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
    }
}

CallExpressionTaggedTemplateExpression共有一个callTarget,因此您只需使用CallLikeExpression即可始终从callTarget调用表达式属性。

如果你想获得将被调用的参数,你可以使用getEffectiveCallArguments提取它,它知道如何处理两者之间的差异。