GoogleAppsScriptは何で書くべきか(公式orローカル / JSorTS )

# 初めに

ライブラリ等でメリットデメリットが大きく変わってくるため、
大雑把になっています

# GoogleAppsScriptを書く手段

- 公式サイトで作成する
    - 公式エディタ([https://script.google.com](https://script.google.com))でJavaScriptで記載する
- ローカルで作成する(EditorはVSCode)
    - JavaScriptで記載し、そのままclaspでpushする
    - TypeScriptで記載し、そのままclaspでpushする(自動でトランスパイルされる)
    - JavaScript/TypeScriptで記載し、webpack等を使ってビルドして、claspでpushする

# それぞれのメリット・デメリット

## 公式エディタを使って、JavaScriptを使う

### メリット

- ライブラリ,サービスの使用やデプロイを、GUIで書ける
- JSDocで型を記載できる(paramとreturnしか使えない)
- 一応Gitが使える(拡張機能をインストールする必要がある[Google Apps Script GitHub アシスタント](https://chrome.google.com/webstore/detail/google-apps-script-github/lfjcgcmkmjjlieihflfhjopckgpelofo))

### デメリット

- 型チェックは行われない
- フォーマットは公式エディタ依存(多分任意の設定はできない?)
- 非推奨のメソッドが表示されない(リファレンスには書いてあるがエディタだけでは不明)
- Node.jsのパッケージは使えない
    - ただし、ライブラリでGASでも使えるようにされていれば可能
        - 例： [Cheerio](https://github.com/tani/cheeriogs)
- 複数人での開発が困難
    - 2人以上が編集する場合、あるいは一人でも複数のブラウザで開いていると、
      一人がアップデートしても、もう一人はリアルタイムで反映されず再度読み込む必要がある。
      また、更新せずに、古い状態で実行すると古いもので上書きされてしまう
 
## ローカルでJavaScriptで記載し、そのままclaspでpushする

### メリット

- Node.jsのパッケージを使うことができる(requireとかimportは使えない(後述するwebpack等でビルドすれば可能))
    - ここでのパッケージが使えるは、あくまでコードフォーマッターやhuskyなどといった、コードに直接依存しない範囲の話
- [@types/google-apps-script](https://www.npmjs.com/package/@types/google-apps-script)をインストールしておけば補完は公式と同様に使える
- 任意のコードフォーマッターを使うことができる(ESLint/Prettier...etc)
- CI/CDを使ってpushすることができる
- CI/CDやGitHubを使うことで複数人で開発することが可能
- ローカルで作成したデータをコンパイルされずにそのままpushできる
    - 引数のヘルプがObjectでも正しく表示される(TypeScriptでビルドされるとObjectは正しく表示されない)
      ![スクリーンショット 2022-08-26 0.55.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/4ceca2a7-d46f-a0d6-b2aa-a9a970913d99.png)


    - ただし、ライブラリとしてインポートすると引数をオブジェクトにするとわからなくなる
      
      普通の引数にした場合
      ![スクリーンショット 2022-08-26 0.56.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/f34dc886-948a-6f1a-7af6-72a62239fda3.png)

      Objectの引数にした場合
      ![スクリーンショット 2022-08-26 0.57.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/829f1939-065b-165b-faa2-acbd9b7504dd.png)

      



### デメリット

- import,export,requireが使えない(後述するコンパイルするライブラリを使えば可能)

## ローカルでTypeScriptで記載し、そのままclaspでpushする

### メリット

- TypeScriptで書ける!(型補完)
- claspでpushしてもトランスパイルされる
    - ただしTypeScriptのバージョンは公式に依存する
      ~~2022/08/25時点でのtypescriptのサポートは3.8.2 [clasp/typescript\.md at master · google/clasp](https://github.com/google/clasp/blob/master/docs/typescript.md#typescript-support)~~
      typescriptのlatestは4.7.4
      
      :::note warn
      package.jsonは`typescript@4.7.4`,`@google/clasp@2.4.1`になっていたが、
      clasp pushでは`TypeScript 4.7.3`でコンパイルされていた

      VSCodeのTypeScriptのバージョンか何かに依存している???
      確認方法がわからないので誰か教えてください


### デメリット

- import,export,requireが使えない(後述するコンパイルすれば可能)
- 引数のヘルプがObjectの場合,正しく出力されない(ただしコンパイルされたスクリプトに手動で記載することはないと思うのでほぼデメリットではない)

    JavaScriptでそのまま書いた場合
    ![スクリーンショット 2022-08-26 0.58.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/a2759e38-d0d8-4b3a-70d7-78340917f3bb.png)

    TypeScriptでコンパイルされた場合(引数object)
    ![スクリーンショット 2022-08-26 1.00.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/7e5c16cd-9288-8b63-3574-3c26624d95c2.png)

    普通の引数にした場合は表示される
    ![スクリーンショット 2022-08-26 1.01.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/64e6178c-850b-95b7-7364-6658685b063e.png)

## ローカルでJavaScript/TypeScriptで記載し、webpackでビルドしてからpushする

### メリット

- import,export,requireが使えるため、さまざまなライブラリを使用することができるようになる
- [gas\-webpack\-plugin \- npm](https://www.npmjs.com/package/gas-webpack-plugin)を使えば`global.functionName`で表示する関数を選べるため、内部で使用する関数は非表示にすることができる

### デメリット

- 引数はTypeScriptをそのままclasp pushでコンパイルされたものと同様
    - ただし、書き方によっては引数が正しく機能しないので注意する必要がある
      TypeScript
      ![スクリーンショット 2022-08-27 16.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/f7eb8839-8bf6-b901-e6e8-101014f6afe5.png)
      gas-webpack-pluginでビルドしたファイル
      ![スクリーンショット 2022-08-27 16.20.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/78cfaf77-1a11-7ef1-4e14-6fae98acd850.png)

        :::note info
        ただimportしてきたものをglobalに入れただけでは、
        引数はないとみなされてしまうため(importFormatLogging)、
        globalにはちゃんと引数をいれた関数とした方がいい


# まとめ

Node.jsが使えるのであればローカルで使う方が無難、
複数人で開発する場合は尚のこと。
npmとかが使えないなら、公式のブラウザエディタを使った方が良い。

ローカルで開発する場合、
JavaScriptを使うか、TypeScriptを使うかは、好みにもよるが、
関数の引数をObjectにするとヘルプの表示はイマイチなので、
普通の引数として使用するならTypeScriptで問題ない。

どうしてもObjectで使用したい場合は、
JavaScriptで書いた方がまだわかりやすい(`functionName(_a: any)`となると何もわからない)


個人的にはTypeScriptで作成し、ライブラリとしても使えるようになって欲しいが、
ReactでObjectの引数に慣れすぎたので、
通常の引数で作成することを心がけようと思います。
（通常の引数って言い方で良いのだろうか）