はじめに
VSCodeを使用していると、自動で?.(オプショナルチェーン)を付与してくれます。半年前の自分は「オプショナルチェーンでundefined(null)対応ができてるんだなー」というふわふわ認識だったので、この記事を贈ることにしました。
タイトルにある「左辺に?.があると代入できない」とはこういうことです。
// 代入式の左辺には、省略可能なプロパティ アクセスを指定できません。ts(2779)
hoge?.property = 'fugafuga'
この式の意図は「hoge.property に 'fugafuga' を代入したい。」ですね。もっと付け加えると、「hoge.property に 'fugafuga' を代入したい。ただし、hogeがundefinedかnullのときは何もしない」です。
「オプショナルチェーンでundefined(null)対応ができてるんだなー」の認識だった自分はなんでこれで怒られてるのかわかりませんでした。
結論
hogeがnullもしくはundefinedのとき、左辺がまるごとundefinedとなるので、undefinedに代入をしてしまうことになるから。
↑記事を書いてるうちに「本当か?」となってしまった。とりあえずオプショナルチェーンに代入をしてはいけない「イメージ」として載せておく。
// こんなことをしようとすることになる?
undefined = 'fugafuga'
?.(オプショナルチェーン)について
とりあえずMDN。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining
ざっくり、?.の左が undefined か null の場合はそこで終了してundefinedになってくれます。
// id="hoge"の要素があれば hogeElement にその要素が入る。なかったらnullが入る
const hogeElement = document.getElementById('hoge')
hogeElement?.textContent
↑?.の箇所でhogeElementがnull または undefinedかどうかのチェックがされます(今回はundefinedの可能性はないですが)。
チェックの結果、hogeElementがnull または undefinedであれば「hogeElement?.textContent」はundefined となります。
左辺に?.を書くと
const hogeElement = document.getElementById('hoge')
// 怒られる
hogeElement?.textContent = 'fugafuga'
↑もしこう書いたら、hogeElementがnullだった場合、左辺はundefinedになります。
そのばあいundefinedに代入を試みていることになりそうです。
それは変なので、左辺にオプショナルチェーンはかけない、というイメージでいます。
null や undefined でないときのみ代入したいときはどうするの
さて、この記事を書きはじた理由は「Null合体代入(??=)を使えば短くかけるのでは?」と思ったからです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_assignment
すなわち、「オプショナルチェーンによりundefinedと評価されなければ代入する」ができると思いました。
しかしながらこの書き方もエラーが出てしまいます。とにかく代入式の左辺にはオプショナルチェーンはかけないようです。
const hogeElement = document.getElementById('hoge')
// 残念ながら怒られる
hogeElement?.textContent ??= 'fugafuga'
結局早期リターンするか
if(!hogeElement) return
hogeElement.textContent = 'fugafuga'
&& を使用するのがいいのでしょうか
hogeElement && (hogeElement.textContent = 'fugafuga')
いずれもhogeElementを2回書かないといけないのが引っかかります。
とはいったものの、今まで早期リターンで書いていて困ったことはないので、気長に探してみます