【JavaScript】TypeScriptっぽい構文が書けるようになるTypes as Commentsのティザーサイト紹介

JavaScriptでTypeScriptっぽい構文が書けるようになるproposal、[Types as Comments](https://github.com/tc39/proposal-type-annotations)の[ティザーサイト](https://tc39.es/proposal-type-annotations/)が公開されています。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/e7f66744-eb66-bb2f-0624-d859c3dfb648.png)

ティザーサイトなので当然ですが、あまり詳細な動作までは書かれていません。
このようなことができるようになる、という紹介がメインです。

そして日本語版がなかったので以下はティザーサイトの紹介です。

# Types // as Comments ECMAScript Proposal

## Goal

ECMAScript言語仕様に、静的型構文の仕組みを導入します。
JavaScriptエンジンは、型構文をコメントとして扱います。

### Before

```js
const message: string = "Hello, types"
console.log(message)
```

:::note alert
SyntaxError: Unexpected token ':'. const declared variable 'message' must have an initializer.
:::


### After

```js
const message: string = "Hello, types"
console.log(message)
```

エラーが出ない。

Types as CommentsのProposalは、モダンなJavaScriptコードベースにおける作業を容易にすることを目的としています。
本Propsalにより、開発者はアプリケーションをビルドする必要がなくなり、TypeScriptやFlowのコードをそのまま実行できるようになります。

本Propsalは、型構文そのものを厳格に規定するものではありません。
型構文を受け入れるための空間を提供するためのものです。


## How the proposal works

以下はProposalの簡単な概要です。

```js
const message = "Hello, types"
 
/* Echo the message */
console.log(message) // Hello, types
```

現在のJavaScriptは、`/*`を複数行コメントの開始地点と規定しています。
JavaScriptエンジンはこれを、『`/*`が現れたら`*/`が出てくるまでの文字を全て無視する』と解釈します。

```js
const message: string = "Hello, types"
 
/* Echo the message */
console.log(message) //Hello, types
```

最も単純なケースを例としますが、本Proposalもこれまでと全く同じような処理を行います。
JavaScriptエンジンは変数名の直後に`:`を見つけると、それ以降のコード部分をコメントとして扱います。
今回の例では`=`が出てきたところでコメント扱いを終了し、結果として`: string`が無視されます。

最終的にJavaScriptのランタイムには、以下のコードが渡されることになります。

```js
const message         = "Hello, types"


console.log(message) // Hello, types
```

実際の実装では、もう少し複雑な処理が必要となるでしょう。
たとえばオブジェクト型リテラル`({ id: string })`をパースするために中括弧`{}`の開閉を追跡する、などです。

本Proposalの目的は、JavaScript言語仕様が、型構文っぽいコードを無視する方法を規定することです。


## Who benefits?

誰が利益を受ける？

### JavaScript and TypeScript Users

JavaScriptとTypeScriptのユーザ。

最近のJavaScriptプロジェクトにありがちな、ソースコード変換の手間が減らせます。
JSDocより強力かつクリーンな構文を使用できます。
コンソールやREPLに、TypeScriptのコードをコピペするだけで動くようになります。

### Tool Makers

ツール制作者。

無視される型構文を利用して、新しく実験的な構文を試すことができます。
既存のJavaScriptツールにも利点があります。
・ソースコード変換しなくてもよくなる。
・ソースマップの必要性が薄れる。
・自力で構文解析せずに済む。


### Engine Maintainers

JavaScriptエンジンのメンテナ。

実際には実行時の型チェックを行わないため、ブラウザエンジンは型チェックにコストをかける必要がありません。
構文を解釈しないことで、開発者はTypeScriptのアップグレードに追随する負担を避けることができます。


## Frequently Asked Questions

Proposalにも総合的なFAQがありますが、以下のFAQで大半の疑問は解決すると思います。

### What type syntax is proposed?

どのような型構文が提案されていますか？

関数や変数宣言の型定義、型のインポート/エクスポート、クラスフィールドとメソッド、ジェネリクス、アサーション、`this`、などなど。

### Will JavaScript engines perform type-checking?

JavaScriptエンジンで型チェックができるようになるのですか？

いいえ。
型チェックを行うのは、TypeScriptやFlowなどの型システムの役目です。
本proposalが行うのは、彼らのために型構文が存在できる余地を確保することです。

### Will adding types slow down my JavaScript programs?

型を追加することでJavaScriptの実行速度が遅くなってしまうのでは？

その他のJavaScriptの新機能と同様、パフォーマンスとのトレードオフになることは確かです。
ただ、ここでの型構文は単にコメントして扱うだけなので、パフォーマンス上の影響は相当に少なくないものになるでしょう。

要するに、いいえ。

### Will this grow JavaScript bundle sizes?

JavaScriptのバンドルサイズが大きくなってしまうのでは？

現在既にバンドルプロセスを使用しているのであれば、そのプロセスにおいて既に型構文は削除されています。
既存ツールのほとんどは、今後も型構文を削除し続けることでしょう。

ビルドを行わない場合は型構文のぶんだけサイズが大きくなります。
これはコメントを記述するのと同じトレードオフであり、minifierを適用するなど、コメントを記述するのと同じ解決策が適用可能です。


### How does this differ from JSDoc support?

JSDocとの違いは何ですか？

現在、JavaScriptではJSDocのコメントを書くことでも、TypeScriptやClosure Compilerの型チェックを行わせることができます。

JSDocの構文は型構文より複雑であり、さらに複雑な型付けが困難です。
このプロポーザルによって、JSDocの制限を受けずに、JSDocのようにビルドツールなしで動作する環境を得ることができます。

### Does this proposal favor TypeScript?

このプロポーザルはTypeScriptに忖度している？

このプロポーザルは、TypeScriptにFlowいずれの構文も使えるようにするものであり、さらに両者に限らない新しい構文も受け入れることができます。

TypeScriptが最も人気のある型構文であるため、TypeScriptに大きく影響されていることは否定できませんが、提案のほとんどはFlowにとっても有益なものです。


### Is there prior art?

先行技術はありますか？

Pythonも、同様な型チェック機構をサポートしています。
本proposalでは、型構文を消去するだけという面が強くなっています。


### Will this slow down JavaScript's evolution?

これはJavaScriptの進化を遅らせることにならない？

古いコードを壊さないというJavaScriptの後方互換性は、将来のJavaScriptの構文改良において本proposalを考慮しなければならいことを意味します。
しかし、本proposalはコードとして実行されるわけではなく、厳密に規定されたコメント構文にすぎないため、新しい構文の妨げになることはほとんどないでしょう。


### How does this affect runtime error messaging?

ランタイムエラーへの影響は？

エンジンが発行できる新しいエラーは、せいぜいSyntaxErrorsだけです。

本proposalは、一見無効な構文に思えるけど実際は問題ない、という余地が多分にあります。
例として以下の構文は、TypeScriptやFlowではエラーになりますが、本proposalでは問題なく動作します。

```js
const message: { abc=123 } = "Hello, types"
```

いっぽう、本proposalにおいては、型構文に関して幾つかの制限があります。

```js:シンタックスエラー
const message: !!@@hello@@!! = "Hello, types"
```

このproposalでは、型が不正な場合に発生するエラーは、全てIDEや型チェッカーに任せます。


### I'm new, what are these terms?

初心者なんですけど、けっきょくこれは何？

JavaScriptは、値の定義を宣言する方法を提供しない言語です。
たとえばJavaScriptでは、1つの変数に文字列、数値、オブジェクトなどなんでも入れることができます。

TypeScript、FlowといったJavaScriptの拡張言語は、「この変数は絶対に文字列しか入れることができない」を表す構文を取り入れました。

そのような構文を追加する利点は、コードがどのように動作するかをより厳密に定義し、問題があるときにすぐ検証できることです。
検証はエディタ自身に搭載することもできますし、コマンドラインツールもあります。

この検出プロセスは型チェックと呼ばれます。
JavaScriptには、コードをどのように検証するかについて異なるトレードオフを持つツールが幾つも存在します。

本proposalの提出以前は、型宣言を取り除くためにはBabelやTypeScriptといった外部ツールが必要でした。
本proposalが受理されると、型を取り除くための外部ツールは必要なくなります。

型を取り除くステップを踏まなくてもよくなるため、JavaScriptプロジェクトの運用が簡素化できます。
もしかしたらビルドツールが全く不要になるかもしれません。


### What does the grammar look like?

文法の仕様はどこですか？

[文法の完全な仕様はこちら](https://tc39.github.io/proposal-type-annotations/grammar.html)。
[実装上の注意点などはこちら](https://github.com/tc39/proposal-type-annotations/blob/master/syntax/grammar-ideas.md)です。


## Frequently Asked Questions about TypeScript

TypeScriptに関するFAQ。
このトピックに関する[ブログ](https://devblogs.microsoft.com/typescript/a-proposal-for-type-syntax-in-javascript/)もあります。

### Will all of TypeScript be supported by this proposal?

このproposalは、全てのTypeScript構文をサポートしているのでしょうか？

いいえ。
全てのTypeScript構文をサポートしているわけではありません。
これは、Babelが全てのTypeScript構文をサポートしていないのと同様です。

たとえば列挙型、名前空間、クラスのParameter propertiesなどはサポートされることはないでしょう。
また関数の呼び出し先で型引数を指定する場合は、少し異なった構文になります。


### How would I convert my TypeScript codebase to JavaScript with Types as Comments?

TypeScriptのコードベースを本proposalに移行するにはどうすればいい？

TypeScriptに、本proposalと互換性があるかを確認するオプションを追加する必要があります。
開発チームは発生したエラーに順次対応していき、エラーが発生しなくなったら最後に拡張子を`.ts`から`.js`に変更して移行完了です。


### How does this differ from JSDoc support?

JSDocとはどう違う？

JSDocは既存のコメント中に型情報を入れることで、このproposalと同じ問題を解決しています。
JavaScriptの言語仕様を変更せずに型チェックを導入するためには、これが最善の妥協点だったのです。

本proposalでは言語仕様を変更しないという制約を取り払い、言語仕様を変更して型構文を取り入れるものです。
この変更によって、ただのJavaScriptでありながら、型チェック機構も取り入れられます。
TypeScriptのJSDocサポートの利点を全て受けることができ、なおかつ構文も簡素です。


### Do I need to migrate?

マイグレーションは必要？

いいえ。
TypeScriptは後方互換性を保証しているため、現在の`.ts`や`.tsx`は本proposal適用後も引き続き使用可能です。
今日動作しているコードは、明日も明後日も動作します。

このproposalはまだ採用されていないため、既存のコードを今から本proposal対応に書き替え始めるのは時期尚早です。
しばらく待つことをお勧めします。


## Links

このページは、Type as Commentsの簡単な概要について紹介しました。
もっと詳細を知りたい場合は、GitHubリポジトリを参照してください。

### [Motivations](https://github.com/tc39/proposal-type-annotations#motivation)

動機。

この提案が、JavaScriptのエコシステムをいかに改善するのかについて。

### [Supported Syntax](https://github.com/tc39/proposal-type-annotations#proposal)

サポートされる構文。

型定義からクラスのプロパティまで、サポートされる型構文はこちら。

### [Frequently Asked Questions](https://github.com/tc39/proposal-type-annotations#faq)

よくある質問。

TypeScriptやFlowのサポートなど、多くのFAQがあります。


# 感想

本文でも記載がありますが、決してブラウザでTypeScriptを動かすわけではなく、TypeScriptっぽい見た目のコメントを導入するというだけのProposalです。
つまり、以下のコードは正しいJavaSctiptとして扱われます。

```js
const a:number = "hoge";
```

実際に型宣言のチェックを行うためには結局外部ツールに頼らないといけないわけで、JavaScriptの型の厳格化に役立つかというと、却ってカオスなコードが増えそうな気がしないでもありません。
なんかType as Comments導入前後とTypeScriptでそれぞれ動作が異なるコードとか書く奴とか出てきそうじゃね。

では何故このようなProposalを推しているのかというと、要するにTypeScriptのコードが概ねそのままブラウザで動くのです。
これによって、TypeScriptを書いたうえでわざわざJavaScriptに変換するという、フロントエンドに蔓延る謎の儀式を省くことができるようになるわけです。

まあ、TypeScriptコンパイラいっこ消しただけで謎儀式が消滅するかというと、それ以外にも様々なことをやっているので、いきなり消えることはありませんけどね。
それでも本proposalのように、余計な手順をひとつひとつ潰してブラウザに吸収させていくことで、ブラウザひとつで済んでいた古き良き？時代のJavaScriptにいつかは回帰できるかもしれませんね。