どういうこと
適当なApps Scriptオンラインエディタで試してみてください。保存時にエラーになるはず(2024/10/20 現在)
// クラスフィールドでの定義はエラーになる class Human{ static category; } // constructorでの定義だと大丈夫 /* class Human{ constructor(){ this.category = "animal"; } } */
経緯
基本的にApps Scriptの開発はclasp
で行っていますが、とあるコードでclasp push
したらエラーが返ってきました。
⠧ Pushing files…Push failed. Errors: GaxiosError: Syntax error: ParseError: Unexpected token ; line: 56 file: main.gs ...略 response: { ...略 }, code: 400, errors: [ { message: 'Syntax error: ParseError: Unexpected token ; line: 56 file: main.gs', domain: 'global', reason: 'badRequest' } ] }
当然のようにminifyをしていた(esbuild-gas-pluginを使っています)のでいったん解除してちまちま追ってみると、どうやらクラス構文の箇所でエラーが出ている様子。これは本題とは関係ないですがこちらの記事からお借りしたコードをほぼそのまま使ったものです。
export class Failure<E extends Error> { readonly error: E; constructor(error: E) { this.error = error; } isSuccess(): this is Success<unknown> { return false; } isFailure(): this is Failure<E> { return true; } } export class ErrorResponse extends Error { readonly name: string; readonly message: string; readonly stack?: string; constructor( readonly functionName: string = 'unknown functionName', readonly statusCode: number = 500, readonly code: ErrorCode = 'APP_UNKNOWN_ERROR', readonly error: Error = new Error('unknown error'), ) { super(); this.name = error.name; this.message = error.message; this.stack = error.stack; } }
そんでもって、わたしの環境の設定でビルドすると、以下のようなコードが生成されていました。
// src/server/types.ts var Failure = class { error; constructor(error) { this.error = error; } isSuccess() { return false; } isFailure() { return true; } }; var ErrorResponse = class extends Error { constructor( functionName = 'unknown functionName', statusCode = 500, code = 'APP_UNKNOWN_ERROR', error = new Error('unknown error'), ) { super(); this.functionName = functionName; this.statusCode = statusCode; this.code = code; this.error = error; this.name = error.name; this.message = error.message; this.stack = error.stack; } name; message; stack; };
これはクラス定義がクラスフィールドで書かれたもので、ES2022で導入された記法のようです。ChatGPTに教えてもらいました。いつもありがとうね。
どうやらGoogle Apps Scriptのランタイムではまだクラスフィールドに未対応の様子です。
対応
ビルド用のスクリプト(さっきも書きましたが、わたしはesbuild-gas-pluginを使ってます)でtargetをES2021
と明示的に書き換えると、エラーなくpushできました。
import esbuild from 'esbuild'; import { GasPlugin } from 'esbuild-gas-plugin'; esbuild .build({ entryPoints: ['src/server/main.ts'], bundle: true, outfile: 'dist/main.js', minify: true, // format: 'esm', export文が生成されてしまうのでやめとく logLevel: 'info', target: 'ES2021', // Apps Scriptでは現状、クラスフィールド未対応らしい plugins: [GasPlugin], }) .catch((e) => { console.error(e); process.exit(1); });
いやーまいった。配列やオブジェクトのメソッド周りは意外と最近のECMAScriptに追従しているイメージだったんですが(Array.prototype.toSorted
(ES2022)とかArray.prototype.toSpliced
(ES2023)とか、Set.prototype.difference
(ES2024)とかは使用可能なのを確認してます)、クラス構文でエラーになるとは。特殊な環境なのでいろいろ罠がありますね...