打字稿中存在一行检查映射项并进行处理?



在typescript中,我看到在执行代码之前检查项目不是null/undefined是很常见的。例如,在打印变量之前检查它是一个数字而不是undefined:

const printNum = (n: number) => console.log(n);
const x: undefined | number = undefined;
x && printNum(x);

我想对Map对象做类似的事情,即检查项目是否存在于Map中,如果存在则执行一些代码,全部在一行。

目前我能想到的唯一方法是使用Map.has()检查它是否存在,然后使用Map.get(),但转换为适当的类型,如下面的示例Map.get()仍然返回类型undefined | A。或者,将项目检索到一个变量中,然后检查null/undefined(但这超过2行)。是否有一个更优雅或更简单的解决方案我错过了?

class A{
constructor(public n: number) {}
}
const printA = (aObj: A) => console.log(aObj.n);
let m = new Map<string, A>([
["firstItem", new A(10)],
["secondItem", new A(20)]
]);
// better way to do this?
m.has("firstItem") && printA(m.get("firstItem") as A);
// or could do it this way
const a = m.get("firstItem");
a && printA(a);

如果A知道如何通过调用printAprint方法来打印自己,您可以使用可选链接:

m.get("firstItem")?.print();
//                ^^−−−− optional chaining

但是如果它是一个单独的函数或其他对象上的方法,那将不起作用。

撇开"更好"的主观定义,在get之后进行has检查意味着在Map中查找键两次而不是一次。在99.99%的地图中(至少😀),这并不重要,但我会这样做:

const item = m.get("firstItem");
if (item) {
printA(item);
}

你不需要断言,因为TypeScript可以从检查中看出item不会是undefined

有些人会把花括号去掉,改成两行:

const item = m.get("firstItem");
if (item) printA(item);

您也可以使用&&:

const item = m.get("firstItem");
item && printA(item);

但是我不认为在一个单独的语句中有一个合理的方法来完成它。我认为大多数人会认为un是合理的:

const item = m.get("firstItem"), _ = item && printA(item);

创建一个从未实际使用过的_常量。但是,当然,如果你再做一次,你必须使用_2或其他东西。

最新更新