GASはTypeScript × claspでストレスフリー開発

**記事を書き終わった後に全くLINE Botと関係のないものだと気づきました。。（完全にGASのお話になってます）
LINE BotのAdvent Calendarの作成者さん、すみません、、、:bow_tone1:**
# はじめに
弊社で使うLine botを作成した時に得た経験（GASストレス）を還元しようと考えたので記事に起こしました。

南無。
# 数多のエンジニアをピキらせたであろうポイント
## ES６に対応していない
正直、これが一番ストレスの根源になってると感じます。

let・const、分割代入、ブロックスコープ、アロー関数、Class　...etc

```js

// no let const
let hoge
const hage

// no destructuring
const piyo = ["hage", "piyo", "fuga"]
const fuga = ["hage", "piyo", ...piyo]  // output -> "hage", "piyo", "hage", "piyo", "fuga"

// no allow function
const foo = () => {}

// no class
class Hoge {
  constructor(piyo) {
    this.piyo = piyo;
  }

  getPiyo() {
    return this.piyo
  }
}
```

これら全て使えません。

## ファイルを分割していてもグローバル変数扱い
エディター上でファイルが分割されていても、GAS側は一つのファイルとして認識します。

<img width="371" alt="スクリーンショット 2019-12-05 17.02.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333018/00e4ff61-1540-7bb4-e1ab-55157a4d6b8c.png">
<img width="390" alt="スクリーンショット 2019-12-05 17.03.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333018/37983608-f911-cfea-5357-73d55e9eb30e.png">

実行すると"global"が出力されました。

<img width="701" alt="スクリーンショット 2019-12-05 17.04.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333018/8c495028-970f-db2e-8026-5b1e6ada2d61.png">

:point_up:ハマるポイント：別のファイルで同じ関数名を定義してしまって、想定のしていなかった処理がされる

## コード補完はできるだけ頑張る！

変数に格納された値を推測し、コード補完をしてくれます。

<img width="589" alt="スクリーンショット 2019-12-05 17.59.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333018/0764fd9f-24ad-713f-8801-b6aab909c709.png">

(※ この配列を作成している末尾にセミコロンを忘れると補完してくれません。)

しかし、関数の引数として渡されると先程の補完機能が働かなくなってしまいます。

<img width="243" alt="スクリーンショット 2019-12-05 18.04.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333018/ad561b7a-b4a5-0e02-5f5b-4474a34a76e1.png">

コード補完機能は基本的にめちゃくちゃ弱いです。期待はほぼできません。
でもたまに補完してくれるのが可愛いですね。:point_up:

# ローカルで開発しよう！

GASのエディターからは脱出しましょう。

ローカルの開発環境を立てるためにclaspを使います
> claspはGoogle Apps Scriptをローカル環境で扱うためのライブラリ。
標準でTypeScriptに対応しており、ES6の記法も使えようになる。（非常に重要）

ではウキウキ気分でclaspをインストールしていきます。　ターミナルから以下のコマンドを実行。

```terminal
$ npm i -g @google/clasp
```
続いてログインしましょう。

```terminal
$ clasp login
```
実行すると、ブラウザが開くので「許可」を押して認証完了です。

任意のディレクトリでプロジェクトを作成しましょう。以下コマンドを実行

```terminal
$ npm init -y
$ clasp create hoge_bot --rootDir ./src
```
`clasp create`を実行すると、プロジェクトのタイプを選択できます。適当なものを選択してください。
`--rootDir ./src`で指定したディレクトリの直下はGASにpushされるイメージになります。

## GitでGASのソースコードを管理

エディターから離れられたのでソースコードもGitで管理しちゃいましょう！

```terminal
$ git init
```
node_modulesと.clasp.jsonは管轄外にしておきます。

```terminal
$ touch .gitignore
```

```text:gitignore
.clasp.json
node_modules
```

## ノンストレスコーディング
GASの諸々のライブラリがnpmで配布されているのでインストールしておきましょう！

```terminal
$ npm i -D @types/google-apps-script
```

以上でローカル環境構築は終わりです。
（更にprettier等を導入してコードを綺麗に保つとより気持ちいいです！！）

ソースコードが書けたらGASにpushしましょう。下記コマンドを実行

```terminal
$ clasp push
```
※ `clasp push`はTypeScriptで書かれたコードを自動でトランスパイルしてくれます。
 
# ここでも罠...　importはdefault exportのみしか受け付けられない

下記のように複数のexportされたものは受け取ることができない。

```typescript:src/hoge.ts
export const hoge = "message hoge"
export const piyo = "message piyo"
```

```typescript:src/fuga.ts
import { hoge, fuga } from "./hoge"
```
importしたければdefault exportにしなければならない。

```typescript:src/hoge.ts
const hoge = "message hoge"

export default hoge
```

```typescript:src/piyo.ts
const piyo = "message piyo"

export default piyo
```

```typescript:src/fuga.ts
import hoge from "./hoge"
import piyo from "./piyo"
```

どうしても一つのファイルから複数の値を返したい、、、なんて時は関数を返すようにしてみましょう。

```typescript:src/Messages.ts
const hoge = "message hoge"
const piyo = "message piyo"

type Name = "hoge" | "piyo"

const getMessage = (name: Name) => {
  switch(name){
    case "hoge":
      return hoge
    case "piyo":
      return piyo
  }
}

export default getMessage
```

```typescript:src/fuga.ts
import getMessage from "./Messages"

const message = getMessage("piyo")   // output -> message piyo
```
getMessageでswitch使ってるのがとってもダサいです。もっとかっこいいやり方があるはずなのでご教授ください:relaxed:

# まとめ
**GASのエディターでコーディングしない。**