TypeScript:类型缩小:断言未定义,因此从类型中排除



这两行都在_e[k]:上抱怨错误"Object possible undefined">

obj[k] = typeof _e[k] === "undefined" ? "" : _e[k].toString();
obj[k] = _e[k] === undefined ? "" : _e[k].toString();

_e[k]是许多类型的并集,因此手动类型转换不适用。如何消除错误?

更新:因此,从更普遍的角度来看,我的问题可以表述为:有没有一种方法可以通过检查应该排除的特定类型来缩小变量的类型?

最小示例:

class test {
a!: string;
b?: number;
}
const t: test = { a: "hi", b: 2 };
for (const k of Object.keys(t) as Array<keyof test>) {
console.log(t[k] == undefined ? "LOL" : t[k].toString());
}

存在一个长期存在的错误/问题,即如果属性键是变量,TypeScript不会执行控制流分析来缩小属性的类型:microsoft/TypeScript#10530;它没有得到解决,因为修复程序带来了巨大的性能损失。在您的情况下,这意味着对_e[k]的类型保护检查不会影响_e[k]的后续使用。

我建议的解决方法是将您的索引访问属性分配给一个新变量,并对此进行检查:

const ek = _e[k]; // new variable
obj[k] = typeof ek === "undefined" ? "" : ek.toString(); // no error now

新的变量ek应用了常规控制流类型分析,您的类型保护就起作用了。

不同用例的其他可能性:

  • 如果您已经检查了undefinednull,但编译器无法确定,那么最简单的更改是使用非null断言运算符!:

    obj[k] = typeof _e[k] === "undefined" ? "" : _e[k]!.toString(); // non-null assertion
    
  • 您可以将类型排除代码重构为自己的自包含表达式,这样就不必重新检查原始值。例如:

    obj[k] = (_e[k] || "").toString(); // refactor
    

    该特定代码仅适用于_e[k]可以具有的唯一错误值是undefined""。如果_e[k]可以是0,那么这将给出不同的结果。一般来说,你可以制作一个新功能来做任何你想做的事情:

    function defined<T, U>(x: T | undefined, dflt: U): T | U {
    return typeof x !== "undefined" ? x : dflt;
    }
    obj[k] = defined(_e[k], "").toString(); // refactor 2
    

好吧,希望其中一个能有所帮助;祝你好运

游乐场链接到代码

因此,对于我的用例来说(但在许多其他场景中不会(,一个(相当棘手的(解决方法是:

obj[k] = _e[k] === undefined ? "" : String(_e[k]);

仍然对在更普遍的情况下有效的(更好的(建议感兴趣(见问题更新(

最新更新