【Deno・VSCode】Deno拡張機能が有効な環境でdocumentの補完を有効にする

こんにちは。すずともです。

Deno拡張機能を有効にすると、`.js`、`.ts`などのファイルでDenoのLangage Serverが働くようになります。
Denoのプログラムを書く上でこれは便利な機能なのですが、ホームページを構築しようと埋め込み用のJavascriptファイルを作ると、そのファイルでもDenoの拡張機能が働いてしまいます。

Denoが働いてる環境でホームページ書くことなんてあるの？と思うかもしれませんが、サーバを立ててホームページを公開するときにDenoを使うと便利なんです。

今回の実験に使ったファイルはGithubにあげてありますので、作るのめんどくさい人はcloneしてくださいな。
[kamekyame/serve-static-deno - Github](https://github.com/kamekyame/serve-static-deno/tree/master)

# ホームページを公開するだけのサーバを立てる
servestと呼ばれるモジュールを使うと簡単に作れます。
以下のコードをコピペして実行するだけです。ちなみにこのコードはservestの公式HPから持ってきたものです。
[Host static files](https://servestjs.org/use-serve-static)

```typescript:main.ts
import { createApp, serveStatic } from "https://deno.land/x/servest@v1.3.1/mod.ts";
const app = createApp();

app.use(serveStatic("./public"));
app.listen({ port: 8899 });
```

上記のコードでは、`serveStatic`関数に`./public`と入れることで、publicフォルダ内のファイルを静的ファイルとして提供します。つまり、publicフォルダ内にindex.htmlやjs、cssなどをまとめておけば、http://localhost:8899 でホームページを公開するサーバとなるわけです。

# 公開するホームページでDOM操作をしてみる。
`index.html`は適当に作るとして、そのなかで`main.js`を読み込み、`title`というIDのついたH1タグの中身を変更するとしましょう。ファイル構成はこんな感じですかね。

```
serve-static-deno
  ├ .vscode
  │   └ settings.json
  ├ main.ts
  └ public
      ├ index.html
      └ main.js
```

一応index.htmlも載せておきます。

```html:index.html
<!DOCTYPE html>
<html lang="jp">

  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>

  <body>
    <h1 id="title"></h1>
    <script type="module" src="main.js"></script>
  </body>

</html>
```

main.jsは

```javascript:main.js
const title = document.getElementById("title");

title.textContent = "Hello!";
```

単純なやつですね。
実際に上記のファイル構成で作ってみると、たぶん、`main.js`のdocumentの所がこんな感じになっていると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255360/26b886e9-0175-a006-5efb-4c0078a26e83.png)
※マウスカーソルが見えてませんが、documentの文字の上に載せてます。

`document`が`any`になっていますね。つまり、documentの補完をしてくれません。これだと、`getElementbyID`みたいな打ち間違えも多くなっちゃいます。（特にdom関係の関数名は長いですからね笑）
ちなみに、HTML内にscriptタグを作ってjsを書くと、`Document`型と判断してくれていることが分かります。htmlファイルはDenoの監視下ではないので、補完してくれるというわけですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255360/328e511c-fc4c-6b61-c5aa-20ad3d84be75.png)

# documentの補完のおまじない
なぜdocumentがanyになるか。それは、Denoのプログラムではdocumentが使えないからです。だってDOM操作をする先がないんですからね笑
DenoにはTypescriptのコンパイラがついているのですが、そこでdocumentの補完を無効にしています。
**無効**にしているだけで、有効にすれば補完ができるというわけです！

ってことで、補完を有効にしたいファイルの先頭に以下のおまじないを付けてください！

```javascript
/// <reference lib="dom"/>
```

ただのコメント分じゃん！って思うかもしれませんが、Typescriptのコンパイラは3つスラッシュのコメントを読んでくれるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255360/2a9f4349-886b-7c40-e4e4-32acb24fb551.png)



おまじないによって、補完が効きましたね！

# おまじないの意味
ここからはおまじないの意味までちゃんと知っておきたい！っていうコアな人？(最近使えればいいやって人多くない？)向けの情報です。

Typescriptの公式リファレンスにちゃんと載ってます。
[Triple-Slash Directicves](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html)

typescriptでは、コンパイラオプションに`lib`ってのを渡すことで、どの型定義、構文を使うかを指定しています。
ってことで、documentを補完してほしかったら`lib="dom"`を追加しているってわけです。

ちなみに、Deno内部では独自ライブラリ`deno.window`っていうのを使用しているらしく、これでdocumentの部分などDenoに関係ない部分を消しているんですね。

# 不安定だから気を付けてね
`main.js`に先ほどのおまじないを追加すればいいわけですが、vscodeの拡張機能はそこまで賢くないらしく、関係ないファイルにまでdocumentの補完をしてくれちゃってますw

まぁ、リアルタイムでチェックしてくれてるのに1ファイルだけ使うライブラリが違うって無茶苦茶ですからね笑

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255360/f89d3472-3413-322d-3b89-7a52954c67cd.png)
↑サーバ側の`main.ts`ファイル、documentを補完してしまっている。

なので、誤ってdocument.~を使わないように！
とはいっても、実行時に走るちゃんとした？コンパイラにはエラー吐かれる(tsファイルなら)のでまぁ安心ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255360/c06c6aaf-1039-3811-6e66-768e407f9016.png)
↓エラー文
> error: TS2584 [ERROR]: Cannot find name 'document'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'.
document.body;
> コンパイラの`lib`オプションに`dom`がないから入れたらどう？(意訳)

# 終わりに
最後まで記事を読んでくださりありがとうございました🙇
Denoはまだまだ奥が深く、僕はtypescriptもDenoから学んだので、知識も浅いです。
浅いなりにoutputしていこうかなということで記事を書いています！

言い回しが分かりにくかったり、間違った意味で言葉を使ったりしていたら教えてくれるとありがたいです。

これからもDeno、バンバンつかっていろんな記事書いていきますので、よろしくお願いします。