動作環境
TypeScript: 5.4.5
VSCode: 1.93.1
起きている問題
JavaScriptで書かれた以下のコードをTypeScriptに書き換えた際、読み取り専用プロパティであるため、'style' に代入することはできません。ts(2540)
またはerror TS2540: Cannot assign to 'style' because it is a read-only property.
というエラーが表示されてしまう。
document.getElementById("send").style = "cursor: not-allowed";
ちなみにこのコードを実行すると、ブロック上にマウスカーソルが来ると操作禁止を意味するnot-allowed
に変更するcss文に上書きできる。
解決方法
TypeScriptにて先ほどの動作を警告無しに実装する場合、以下のようにstyleが持つcssTextへ代入します。
document.getElementById("send").style.cssText = "cursor: not-allowed";
// ↑これを追加
JavaScriptでstyleに代入すると何が起きていたのか
なぜTypeScriptでは読み取り専用プロパティであるstyleにJavaScriptは代入し、インラインスタイルを設定することができていたのだろうか。この疑問を解消する説明がMDN web docsのHTMLElement: style プロパティにある。
このプロパティは読み取り専用であり、CSSStyleDeclaration オブジェクトを代入することはできません。とはいえ、style プロパティに文字列を直接代入してインラインスタイルを設定することは可能です。この場合、文字列は CSSStyleDeclaration.cssText に転送されます。 この方法で style を使用すると、要素上のすべてのインラインスタイルが完全に上書きされます。
HTMLElement: style プロパティ - Web API | MDN より引用
強調されてい文章から、styleプロパティにJavaScript上で文字列を代入するとその文字列はCSSStyteDeclaration.cssTextに転送されているようです。そのため型付けが無いJavaScriptでは、読み取り専用とはいえ代入すると転送されているため始めに出したコードが動作するようです。
解決方法で挙げたものでは、転送先のCSSStyleDeclaration.cssTextに直接代入するようにしています。HTMLElementのstyleは動的なCSSStyleDeclarationオブジェクトの形であるため、style.cssTextに代入することで元のJavaScriptで書かれたコードと同じ動作を行えます。