打字稿:联合类型和三元运算符的类型推断

时间:2018-11-13 13:54:59

标签: typescript ternary-operator union-types

下面的打字稿代码可以很好地编译:

let x: 0 | 1 = 0;

console.log(x);

const r = [true, false];
for (const y of r) {
    if (y || (x !== 1)) {
        x = 1;
    } else {
        x = 0;
    }

    console.log(x);
}

但是,此代码在语义上是等效的,但不会:

let x: 0 | 1 = 0;

console.log(x);

const r = [true, false];
for (const y of r) {
    x = ((y || (x !== 1)) ? 1 : 0);
    console.log(x);
}

x !== 1的错误是:

7:17 error TS2367: This condition will always return 'true' since the types '0' and '1' have no overlap.

在两种情况下,运行编译结果都会产生预期的输出,表明x实际上确实取值为0 1:

0
1
0

我理解该错误源于以下事实:在第二种情况下,编译器将类型0 | 1缩小为0。但是,仅通过查看代码,很明显可以x被分配了1(即使不查看条件)。因此,除非另有明确说明,否则我希望类型推断采用最通用的类​​型(如第一个示例中所述)。实际上,在第1行中,我明确告诉编译器我需要更通用的类型:let x: 0 | 1

所以我的问题是,是否有合理的理由说明在三元运算符的情况下类型推断的行为会有所不同?

1 个答案:

答案 0 :(得分:1)

错误实际上是因为编译器将x的类型缩小为0

我不确定在其他情况下为什么没有收到错误-我希望在两种情况下都保持一致-但是我不够聪明,无法编写执行此操作的工具。< / p>

x的类型强制为0 | 1而不是编译器将其范围缩小为零的示例:

let x = 0 as 0 | 1;

console.log(x);

const r = [true, false];
for (const y of r) {
    x = ((y || (x !== 1)) ? 1 : 0);
    console.log(x);
}