奇怪的 TypeScript 错误,值检查中的 ts2367

问题描述 投票:0回答:3

我有一个类似的 ts 课程

class Vector3 {
    //-----PUBLIC VARS

    x: number;
    y: number;
    z: number;


    //-----CONSTRUCTORS

    constructor(x?: number, y?: number, z?: number) {
        this.x = x == undefined ? 0 : x;
        this.y = y == undefined ? 0 : y;
        this.z = z == undefined ? 0 : z;
    }


    //-----METHODS

    SetValues(x: number, y: number, z: number): void {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

我编写了一个单元测试代码作为

function TestVector3() {
    var lhs = new Vector3(1, 2, 3);

    lhs.SetValues(1, 2, 3);
    if (lhs.x != 2 || lhs.y != 6 || lhs.z != 12) {
        throw "a";
    }
    
    lhs.SetValues(-1, 2, 3);
    if (lhs.x != -1 || lhs.y != -2 || lhs.z != -3) {
        throw "b";
    }
}

它在 'lhs.x != -1' TS2367 上出错。 删除行“抛出“a”;”会消除这个错误,如何修复它?

这个错误不应该发生,我认为这太愚蠢了......

typescript tsc
3个回答
0
投票

在这种情况下控制流分析确实是错误的,因为它是乐观的并且假设

SetValues
不会改变类实例。
然而,这是有意的行为:请参阅控制流分析中的权衡#9998

除此之外,你的代码对我来说没有意义。它总是会抛出“a”并且代码的其余部分永远不会到达。

如果您的代码确实是测试代码,那么无论如何您都应该为每种情况提供专用的测试功能。

作为一个令人讨厌的解决方法,你可以使用

@ts-ignore

    // @ts-ignore
    if (lhs.x != -1 || lhs.y != -2 || lhs.z != -3) {
        throw "b";
    }

游乐场示例


0
投票
if (lhs.x != 2 || lhs.y != 6 || lhs.z != 12) {
  throw "a"
}

静态代码分析有其局限性。通过上述检查,您可以将

lhs.x
lhs.y
lhs.z
的类型分别从
number
缩小到
2
6
12

即,一旦到达下一条语句,编译器就知道

x
y
z
的值分别是
2
6
12
。因为否则的话,就会抛出错误,并且不会达到此语句。但在做的过程中

lhs.SetValues(-1, 2, 3);

TS 编译器无法知道此方法调用实际上更改了

x
y
z
的值,因此类型缩小仍然完好无损。现在下面的比较似乎毫无用处,因为编译器仍然“知道”
x
y
z
分别是
2
6
12

if (lhs.x != -1 || lhs.y != -2 || lhs.z != -3) {
    throw "b";
}

0
投票

另一个解决方法是检查

lhs
是否为真。这样你就摆脱了狭窄。

function TestVector3() {
  var lhs = new Vector3(1, 2, 3);

  lhs.SetValues(1, 2, 3); 
  if (lhs && (lhs.x != 2 || lhs.y != 6 || lhs.z != 12)) {
    throw "a";
  }

  lhs.SetValues(-1, 2, 3);
  if (lhs && (lhs.x != -1 || lhs.y != -2 || lhs.z != -3)) {
    throw "b";
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.