Typescript 3.7@beta Optional Chaining operator 使用问题

Typescript 3.7@beta Optional Chaining operator using problem

我正在尝试 typescript 可选链接运算符但抛出了这个异常。

index.ts:6:1 - error TS2779: The left-hand side of an assignment expression may not be an optional property access.

我的示例代码如下

const url = URI({
    protocol: 'http',
    hostname: 'example.org' 
})

// This line throwed
document.getElementById('output')?.innerHTML = url.toString()

如何解决这个问题?

如前所述here

The Document method getElementById() returns an Element object representing the element whose id property matches the specified string.

如果我们去看看what properties the Element base class contains, you will see innerHTML

这意味着确定元素的实例(getElementById的结果)将有一个innerHTML 属性,这就是您收到错误的原因。

const output = document.getElementById('output');
if (output) output.innerHTML = url.toString()

此运算符用于访问深层嵌套值。

我们来看document.getElementById('output')?.innerHTML。这将 return undefined(如果 '#output' 不存在)或 string(如果 '#output' 存在)。而你试图将 string 分配给它。

您正在尝试为可能不存在的对象属性设置一个新值。

是的,可选的 属性 访问权限不能用在赋值的左侧。

您可以在 proposal

中阅读更多相关信息

这个非常短的表达式在 typescript 4.0.3 中非常适合我

let domEl: HTMLElement | null = document.querySelector("#app");
domEl && (domEl.style.color = "green");

你也可以早点解决这个问题 return:

const output = document.getElementById('output');
if (!output) return;

output.innerHTML = url.toString()

像这样对嵌套属性使用它:

if (!item?.text) return;

item.text.text = action.payload.text;

https://medium.com/swlh/return-early-pattern-3d18a41bba8

https://softwareengineering.stackexchange.com/questions/18454/should-i-return-from-a-function-early-or-use-an-if-statement

objectVariableName!.propertyName = 'some value to assign';

Please note the exclamation symbol i.e,!

在 ES12 中,您可以使用逻辑空赋值来做到这一点

document.getElementById('output')?.innerHTML ??= url.toString()

所以只有当左边的表达式不为空时才会发生赋值。

这就像你愿意做的那样

if (document.getElementById('output')?.innerHTML) {
  document.getElementById('output').innerHTML = url.toString()
}

我的例外是:

赋值表达式的 left-hand 端可能不是可选的 属性 访问。

我在打字稿“~4.6.2”中收到了这个错误并解决了它。

let headingDom : HTMLElement | null = document?.querySelector('h1');
if(headingDom) headingDom.textContent = 'Hello World';