TypeScript 5.8のerasableSyntaxOnlyフラグ。enumやnamespaceが消える日が来た
TypeScript 5.8で導入されるerasableSyntaxOnly
フラグを使うと、enum
やnamespace
、クラスのパラメータプロパティ、module
キーワードなどの構文をエラーとして検出できます。これらの構文はNode.jsでTypeScriptを実行する際に非互換な構文であり、本フラグの導入によりNode.jsとTypeScriptの互換性が高まります。
本記事では、erasableSyntaxOnly
フラグの挙動と、なぜこのフラグが導入されたのかを解説します。
erasableSyntaxOnly
フラグの挙動
erasableSyntaxOnly
とは、「削除可能な構文のみ」という意味です。削除可能な構文とは、Node.jsでTypeScriptを実行される際に削除される構文のことです。後ほど詳しく解説します。
erasableSyntaxOnly
フラグは、tsconfig.jsonのcompilerOptions
に"erasableSyntaxOnly": true
を設定することで有効になります。
{
"compilerOptions": {
"erasableSyntaxOnly": true
}
}
このフラグをONにした状態で、enum
やnamespace
、クラスのパラメータプロパティなどの構文を使ってみます。
enum MyEnum {
A,
B,
C,
}
namespace myNameSpace {
export const foo = 1;
}
class MyClass {
constructor(private myField: string) {
this.myField = "foo"
}
}
TypeScript Playgroundで動作を確認すると、各構文がエラーになっていることがわかります。
※ TypeScript Playgroundにて、TS ConfigタブからerasableSyntaxOnly
フラグをONにして動作確認
次のリンクから動作を確認できます。
erasableSyntaxOnly
フラグが導入されたのか
なぜ前提: Node.jsでTypeScriptの型注釈を削除し、そのまま実行できるようになった
最近のNode.jsでは、TypeScriptのコードをそのまま実行できます。従来のようにts-nodeを使う必要はありません。Node.jsがTypeScriptの型注釈を削除し、JavaScriptのコードとして実行しているのです。
Node.js v22.7では --experimental-strip-types
フラグを使う必要がありました。
最新のNode.js v23.6では、フラグすらなしにTypeScriptコードを実行できます。 たとえば次のようなTypeScriptのコードを記述し、
index.ts
というファイル名で保存します。
const myName: string = "とんこつ";
console.log(myName);
index.ts
をNode.jsで実行するには、次のようにnode
コマンドを使うだけです。
node index.ts
実行結果は次のとおりです。
型注釈の削除だけでは実行できないTypeScriptの構文をエラーにする
しかし、enum
やnamespace
、クラスのパラメータプロパティなどの構文は、単純な型注釈の削除ではない変換処理が必要になり、「削除不可能な構文」とみなされます[1]。
erasableSyntaxOnly
フラグが提案されたのは、こういったNode.jsの削除不可能な構文をエラーにし、Node.jsのTypeScript実行との互換性を高める目的がありました。
erasableSyntaxOnly
フラグでエラーとみなされる主な構文は次のとおりです。
enum
namespace
- クラスのパラメータプロパティ
- レガシーな
module
レガシーなmodule
とは、TypeScript独自のmodule
キーワードを使ったコードのことです。以前のバージョンのTypeScriptで使用されていた構文です。
なお、DecoratorsもNode.jsでは削除不可能構文とみなされます[2]が、TypeScriptのerasableSyntaxOnly
フラグをONにしてもエラーになりません。
enum
やnamespace
などの構文がエラーになって困るか?
これは私個人の意見ですが、クラスのパラメータプロパティを除くと直近のコードで使う機会はほとんどありません。
enum
を使っているコードは現場では極稀に見かけますが、enum
のような挙動を実現したければ、次のようにオブジェクトリテラルを定義して、その型を使うようにしています。
const MyEnum = {
A: 0,
B: 1,
C: 2,
} as const;
type MyEnum = typeof MyEnum;
namespace
は、 モジュールと import * as
を使うことで実現できます。
foo.ts
export const myName = "とんこつ";
main.ts
import * as myNameSpace from "./foo";
console.log(myNameSpace.myName); // "とんこつ"
クラスのパラメータプロパティは、次のように実現できます。
class MyClass {
private myField: string;
constructor() {
this.myField = "foo";
}
}
それぞれ、erasableSyntaxOnly
フラグをONにしてもエラーになりません。
※ TypeScript Playgroundにて、TS ConfigタブからerasableSyntaxOnly
フラグをONにして動作確認
唯一悩んでいるのがクラスのパラメータプロパティで、筆者はNestJSのコードを書く際に使っています。NestJSでは、クラスのパラメータプロパティを使った依存性の注入が一般的なので、対応方法を検討中です。
erasableSyntaxOnly
は歓迎すべき挙動
筆者的にはerasableSyntaxOnly
は嬉しい挙動です。とりわけenum
については、生成されるJavaScriptコードが好みでなかったり、オブジェクトで表現したほうが各値のループの表現がしやすかったりで、ESlintで禁止して使わないようにしていました。また、Node.jsで動作するTypeScriptとの互換性が高まったこともメリットです。TypeScript 5.8にアップデートしたら早速フラグをONにするつもりです。
TypeScript 5.8は2025年2月25日にリリース予定ですので、今の内から挙動を試しておきましょう。
参考資料
-
Node.jsでは
--experimental-transform-types
フラグを使うと変換が可能です ↩︎ -
https://nodejs.org/api/typescript.html#typescript-features ↩︎
Discussion