在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
知道如何通过调用printA
的print
方法来打印自己,您可以使用可选链接:
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
或其他东西。