首先,没有关于使用称为联合类型的 TypeScript 新功能的官方指南(截至 2015 年 3 月 8 日的 AFAIK)。好吧,我试图找到一种自己使用它们的方法。这并不容易。我仍在努力寻找联合类型在我的代码中的位置:
- 它们不能与接口(interface)一起使用,因为没有可靠的运行时检查来判断一个值是否实现了一个接口(interface)
- 由于类型推断的问题,它们不能与泛型一起使用:https://github.com/Microsoft/TypeScript/issues/2264
还剩下什么?
- 混合基元(通过 typeof 解构)
- 混合类(通过 instanceof 解构)
我认为这 2 种是目前在 TypeScript 中使用联合类型的唯一有效方式是否正确?
如果是,是否有任何计划扩大其适用范围?
如果不是,我错过了什么?
最佳答案
我不认为你能得到一个单一的答案;至少,联合类型处理许多不同的用例,使用户能够以类似于他们编写规范 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
}
}
CallExpression
和 TaggedTemplateExpression
都有一个共同的 callTarget
,因此您始终可以从 CallLikeExpression< 中获取正在调用的表达式
仅使用 callTarget
属性。
如果您想获得将被馈送到调用中的参数,您可以使用 getEffectiveCallArguments
提取它,它知道如何处理两者之间的差异。
关于typescript - TypeScript 中的联合类型有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28931221/