BLOG ブログ

技術情報

GoogleAppsScriptをTypeScriptで実装

yuji takeichi

yuji takeichi

社内のデータ集計でGoogleAppsScript(以降、GASと表記)を組む機会があり、折角なのでVSCode上でTypeScriptで実装してみました。
本記事ではVSCodeを使ってTypeScriptで実装し、GASへ連携する方法を紹介します。

概要

GASとローカル環境との連携はclasp(GoogleのCLIツール)を使用します。
claspでtypescriptをコンバートしてGASへpushすることができますが、typescriptのimportに対応しておらず複数ファイルに分けての開発ができません。
この問題を解消するためにbundleしたコードをpushするようにします。

プロジェクトの初期化

$ npm init -y
Wrote to C:xxxxxxxxx\package.json:
{
  "name": "blog",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

パッケージインストール

npm i @google/clasp @types/google-apps-script typescript esbuild ts-node
  • @google/clasp: GASのCLIツール
  • @types/google-apps-script: GASの型定義
  • typescript: typescript
  • esbuild: bundleに使用
  • ts-node: エントリポイント生成で使用
  "dependencies": {
    "@google/clasp": "^2.4.2",
    "@types/google-apps-script": "^1.0.83",
    "esbuild": "^0.20.2",
    "ts-node": "^10.9.2",
    "typescript": "^5.4.5"
  }

Googleへログイン

$ clasp login
Warning: You seem to already be logged in *globally*. You have a ~/.clasprc.json
Logging in globally…
🔑 Authorize clasp by visiting this url:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

ブラウザが起動して以下の画面が表示されるので、連携するアカウントを選択する
権限の許可なども求められるので適宜案内に沿って次へ進みます。

ログインが完了すればブラウザに以下のメッセージが表示されます。

Logged in! You may close this page. 

GASプロジェクトのClone

ブラウザよりスプレットシートからGASのページを表示するとURLが以下のようになっています。

https://script.google.com/u/0/home/projects/XXXXXXXXXXXXXXXXXXXXXXXXX/edit

「XXXXXXXXXXXXXXXXXXXXXXXXX」の部分がスクリプトIDとなっており、以下のコマンドでCloneすることができます。

$ clasp clone XXXXXXXXXXXXXXXXXXXXXXXXX
Cloned 2 files.
└─ C:\xxxxxxxx/コード.js
└─ C:\xxxxxxxx/appsscript.json
Not ignored files:
└─ C:/xxxxxxxx/appsscript.json
└─ C:/xxxxxxxx/src/main.ts
└─ C:/xxxxxxxx/コード.js

Ignored files:
└─ C:/xxxxxxxx/.clasp.json
└─ C:/xxxxxxxx/package.json

tsconfig.jsonの作成

tsファイルをjsファイルにコンパイルするためにtsconfig.jsonを作成します。

npx tsc --init

src/main.tsの作成

srcディレクトリとmain.tsを作成します。
GASのエントリポイントにしたい関数はexportするようにします。※理由は後述

$ mkdir src
$ touch src/main.ts

distディレクトリの作成

GASへpushするファイルはdistディレクトリに出力しようと思うので、distディレクトリを作成します。
また、pushするファイルが格納されているフォルダにappsscript.jsonが配置されている必要があるので、clasp cloneを行った際にcloneされたappsscript.jsonを移動します。

mkdir dist
mv appsscript.json dist/$1

.clasp.jsonの更新

distフォルダ内のファイルをpushしたいため、.clasp.jsonのrootDirをdistに変更します。

{
    "scriptId":<スクリプトID>,
    "rootDir":"dist",
}

bundle

claspではtypescriptのimport文はコメントアウトされてしまいます。
importに対応するため、edbuildにてbundleを行います。

npx esbuild src/main.ts --bundle --outdir=dist --format=iife --global-name=_entry

build

bundleしたことによって、各関数は_entryオブジェクトの内部関数になっており、GASのエントリポイントとして認識されなくなってしまっているので、GASに対するエントリポイントを作成する必要があります。
'./src/main.ts'でexportされている関数をビルド後のjsファイルへ関数定義し、GASのエントリポイントにします。

npx ts-node -T build.ts

build.tsの作成には以下サイト参考にさせていただきました。

参考サイト:https://zenn.dev/terass_dev/articles/a39ab8d0128eb1#%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E3%81%95%E3%82%8C%E3%81%9F%E9%96%A2%E6%95%B0%E5%90%8D%E3%81%AE%E5%8F%96%E5%BE%97

GASへpush

claspのコマンドを使ってGASへpushします。
dist配下のコードがpushされます。

clasp push

おまけ

修正するたびにbundle、build、pushと行わないといけないので、
package.jsonでscriptにしておくと楽ですね。

"scripts": {
    "bundle": "esbuild src/main.ts --bundle --outdir=dist --format=iife --global-name=_entry",
    "build": "npm run bundle && ts-node -T build.ts",
    "push": "npm run build && clasp push"
}

yuji takeichi

yuji takeichi