支援対象地域:札幌、仙台、関東、愛知、関西、広島、福岡

  • TOP
  •   
  • コラム
  •   
  • TypeScriptとは?詳しく解説

概要

ここではTypeScriptについて説明させていただきます。
TypeScriptは、マイクロソフトが開発したオープンソースのプログラミング言語で、JavaScriptに基づいて構築された厳密に型指定されたプログラミング言語であり、あらゆる規模で優れたツールを提供します。JavaScriptにコンパイルするように設計されているため、ブラウザー、または Node.jsやElectronアプリなどの他のコンテキストで使用できます。 TypeScriptは2012年から存在しており、それ以来、コミュニティのフィードバックの助けを借りて進化してきました。
以上が簡単ではありますがTypeScriptの概要となります。
さらに詳しくTypeScriptについて解説させていただきます。

TypeScriptの特徴

TypeScriptの特徴について説明させていただきます。
一点目がJavaScriptです。 JavaScriptに追加の構文を追加して、エディターとのより緊密な統合をサポートします。エディターで早い段階でエラーを見つけます。
二点目が信頼できる結果を提供する点です。 TypeScriptコードはJavaScriptに変換され、JavaScriptが実行される場所ならどこでも実行されます。
三点目が大規模な安全性です。 TypeScriptはJavaScriptを理解し、型推論を使用して、追加のコードなしで優れたツールを提供します。

詳細

TypeScript言語の基本的な知識について説明させていただきます。
宣言ファイルセクションは、次のセクションに分かれています。
一点目が宣言参照です。 基礎となるライブラリの例しかない場合、宣言ファイルの作成に直面することがよくあります。 宣言リファレンスセクションでは、多くの一般的なAPIパターンと、それぞれの宣言の記述方法を示します。 これらの宣言記述方法は、TypeScriptのすべての言語構造にまだ慣れていない可能性のあるTypeScript初心者を対象としています。
二点目がライブラリ構造です。 ライブラリ構造ガイドは、一般的なライブラリ形式と、各形式の適切な宣言ファイルを作成する方法を理解するのに役立ちます。 新しい宣言ファイルの作成者は、ライブラリの形式が宣言ファイルの記述にどのように影響するかを正しく理解するために必要です。 テンプレートセクションには、新しいファイルを作成する際の便利な出発点となる宣言ファイルがいくつかあります。
三点目が規則ルールです。 宣言ファイルでよくある間違いの多くは、簡単に回避できます。 すべきこととすべきでないことのセクションでは、一般的なエラーを特定し、それらを検出する方法と修正する方法について説明します。
四点目がディープダイブです。 宣言ファイルがどのように機能するか、基本的な仕組みに関心のある経験豊富な作成者向けに、ディープダイブセクションでは宣言の記述における多くの高度な概念について説明し、これらの概念を活用してよりクリーンで直感的な宣言ファイルを作成する方法を示します。
五点目がnpmに発行するです。 公開セクションでは、宣言ファイルを npmパッケージに公開する方法を説明し、依存パッケージを管理する方法を示します。
六点目が宣言ファイルの検索とインストールです。 JavaScriptライブラリのユーザー向けに、Consumptionセクションでは、対応する宣言ファイルを見つけてインストールするためのいくつかの簡単な手順を提供しています。

TypeScriptとJavascript

TypeScriptの詳しい説明の前に、Javascriptについて簡単に説明させていただきます。
JavaScriptは、ブラウザー用の単純なスクリプト言語として誕生し、当初はWebページに埋め込まれたコードの短いスニペットに使用されることが期待されていました。 初期のWebブラウザーではこのようなコードの実行は非常に遅くなりましたが、やがてJavaScriptの人気が高まり、Web開発者はそれを使用してインタラクティブなエクスペリエンスを作成するようになりました。
Webブラウザー開発者は、実行エンジンを最適化し (動的コンパイル)、できることを拡張 (APIを追加)することで、このJavaScript使用の増加に対応しました。

最新のWebサイトでは、ブラウザーが何十万行ものコードにまたがるアプリケーションを頻繁に実行しています。これは、静的ページの単純なネットワークから始まり、あらゆる種類のリッチアプリケーション用のプラットフォームへと進化する長期的かつ漸進的な成長です。さらには、node.jsを使用してサーバーを実装するなど、ブラウザのコンテキスト外で使用されるほど普及しています。
Javascriptのどこでも実行できるという性質は、クロスプラットフォーム開発にとって魅力的な選択肢で、最近では、JavaScriptのみを使用してスタック全体をプログラミングする開発者も多数います。このようにJavascriptの利便性によって爆発的な普及が実施されてきたというのが歴史となります。

詳細

具体的な説明をさせていただきます。
TypeScriptは、構文上、JavaScriptコードをエラーとは見なしません。 これは、どのように記述されているかを正確に気にすることなく、動作するJavaScriptコードを取得し、TypeScriptファイルに配置できることを意味します。ただし、TypeScriptは型指定されたスーパーセットのため、さまざまな種類の値を使用する方法に関する規則が追加されます。
一部のコードをJavaScriptファイルからTypeScriptファイルに移動すると、コードの記述方法によっては型エラーが発生する場合があります。 これらは、コードの正当な問題であるか、TypeScriptが過度に保守的な可能性があるため、開発者はさまざまなTypeScript構文を追加して、エラーを排除する方法を理解する必要があります。

さらにTypeScriptは、JavaScriptの実行時の動作を保持するプログラミング言語でもあります。
原則として、TypeScriptはJavaScriptコードの実行時の動作を決して変更しません。 つまり、コードをJavaScriptからTypeScriptに移動すると、TypeScriptがコードに型エラーがあると判断した場合でも、同じように実行されることが保証されます。
JavaScriptと同じランタイム動作を維持することは、TypeScriptの基本的な約束です。 これは、プログラムの動作を停止させる可能性のある微妙な違いを心配することなく、2つの言語間を簡単に移行できることを意味するためです。 TypeScriptのコンパイラは、コードのチェックが完了すると、型を消去して、結果の「コンパイル済み」コードを生成します。 これは、コードがコンパイルされると、結果として得られるプレーンなJSコードには型情報がないことを意味します。さらに、TypeScriptが推論した型に基づいてプログラムの動作を決して変更しないことも意味します。 要するに、コンパイル中に型エラーが発生することがありますが、型システム自体は、実行時のプログラムの動作には関係ありません。

最後に、TypeScriptは追加のランタイムライブラリを提供しません。 プログラムはJavaScriptプログラムと同じ標準ライブラリ (または外部ライブラリ) を使用するため、TypeScript固有のフレームワークを追加で学習する必要はありません。

比較

JavaScriptとTypeScriptの比較について検討してみましょう。
これらは一概に比較できる内容でなく、まずJavaScriptを学ばなければ、TypeScriptを学ぶことはできないと理解する必要があります。TypeScriptは構文と実行時の動作をJavaScriptと共有しているため、JavaScriptについて学ぶことは、同時にTypeScriptを学ぶのにも役立ちます。

プログラマーがJavaScriptを学ぶために利用できるリソースは非常にたくさんあります。また、それらは現在のソフトウェア開発において必須の知識であることは間違いありません。TypeScriptを作成している場合は、これらのリソースを参考にすることで正しい理解を獲得できるでしょう。
TypeScriptは、コンパイル時の型チェッカーを備えたJavaScriptのランタイムです。TypeScriptでリストを並べ替える方法は、JavaScriptで行う方法と同じです。
あくまでもこれらは一つの例に過ぎません。TypeScriptを直接使用するリソースを見つけた場合、それは素晴らしいことですが、ランタイムタスクの実行方法に関する質問に対しては回答が必要でない場合もありますので、柔軟に学習することが大事です。

SlackとTypeScript

コードを1行も変更せずにTypeScriptを使用できるという、SlackでのJavaScriptからTypeScriptへの移行はニュースとして取り上げられました。これにより、重大なバグ修正や新機能の作業を中断することなく、 コンパイラと静的解析を早期に有効にすることで、「段階的な型付け」を使用することができました。 実際には、コードを変更せずに分析とコンパイラをオンにすると、TypeScriptはすぐにコードを理解しようとします。 サードパーティの依存関係に利用できる組み込みの型と型定義を使用してコードのフローを分析し、 以前は見過ごされていた微妙なエラーを指摘します。 TypeScriptがコードを理解できない場合は、常に「any」と呼ばれる特別な型を想定して先に進みます。
SlackによるTypeScript移行予定はファイルをゆっくりと移植し、可能な限り具体的な型定義を使用してJavaScriptを拡張することでした。 インターフェイスを追加し、クラスメソッドをプライベートまたはパブリックとして定義し、列挙型を宣言します。

その過程において二つの点がポイントとなります。
一点目がコードを変換するときに見つけた小さなバグの数です。 人間が書くコードの行数が増えるほど、プロパティのスペルミスが避けられなくなり、ネストされたオブジェクトの親が常に存在するか、非標準のエラーオブジェクトを使用します。
二点目がエディター統合の機能です。TypeScriptの言語サービスのおかげで、オートコンプリート機能を備えたエディターは、コンテキストを認識した提案で開発をサポートできます。 TypeScriptは、特定のオブジェクトで使用できるプロパティとメソッドを理解し、エディターが同じことを行えるようにします。現在のドキュメント内の単語のみを使用するオートコンプリートシステムは、後で適切でないと考える開発者も少なくありません。 ElectronのBrowser Windowで利用可能なイベントをもう一度チェックして、Googleを検索する時代は終わりました。 プラグインは、Atom、Visual Studio Code、Sublimeで利用できます。さらに、そこにある他のほぼすべてのエディターを離れることなくコードを検証できるため、生産性を向上させることが可能となります。

利点

ReactとNode/npmエコシステムのヘビーユーザーとして、サードパーティライブラリの型定義が利用できることは大きな利点です。
これらの開発者がインポートするライブラリの多くは、既にTypeScriptと互換性があります。 これらは定義がモジュール自体に同梱されていない場合、FixedTypedプロジェクトで見つけることができます。 Reactにはタイプ定義が同梱されていませんが、単純なnpm installでそれらをインストールでき、それ以上の構成は必要ありません。
TypeScriptは、変換を開始してから数日以内にすべての新しいコードにTypeScriptを使用し始めたので、安定性と健全性に非常に役立ちました。デスクトップアプリのコードベースのほとんどのJavaScriptに注釈を付けるのに約6か月かかります。

利点はそれだけではなく、追加のトレーニング費用も大きなメリットです。 厳密に型指定された言語を使用した経験のある開発者は、通常、1時間か2時間以内に構文を習得しますが、TypeScriptのすべての機能をフルに活用するファイルは、JavaScriptのバックグラウンドを持つ開発者には困難に見える可能性があります。
その問題に対する最も明白な解決策は、ゆっくりと機能を段階的に導入することです。コードを変更せずにTypeScriptを有効にして単純な型宣言をいくつか追加し、継承、ジェネリック、高度な型 (交差型、マップ型) などの、より複雑な概念を保存することができます。 特定のモジュールまたは後の段階のいずれかにより、TypeScriptの最も基本的な使い方で多くのメリットを得ることができます。 さらにSlack独自のelectron-compileにより、Electronアプリの開発者は、コンパイル自体について心配することなく、TypeScriptで記述できます。 Slack、Netflix、GitHub、および他の多くの企業で頻繁に使用されているReactive ExtensionライブラリであるRxJSは、SlackのサポートによりTypeScript に移行しました。

最新のアップデート

TypeScriptは最新のアップデートで4.8を発表しました。 直近の4.7とあわせて紹介させていただきます。 TypeScript4.8の新機能は以下の通りです。
一点目が正確性と一貫性の改善です。 直近のアップデートではモードの型変数と制約のない型変数を含むTruthy、Equality、およびTypeofチェックの制御フロー分析に影響を与える多くの変更を導入しました。
具体的には、

  • ・制約のない型パラメータは代入不可
  • ・定義済みのタイプはエイリアス
  • ・{}、null、およびを含む共用体型には、任意の型を割り当て可能
  • ・真偽チェックの制御フロー解析で{}は、真の分岐でジェネリック型が交差
といった変更点があります。

二点目がinferテンプレート文字列型の型の推論の改善です。 TypeScriptは最近、条件型の型変数にextends制約を追加する方法を導入しました。 これらのinfer型がテンプレート文字列型に表示され、プリミティブ型に制限されている場合、TypeScriptはリテラル型を解析しようとします。 これにより、ライブラリが実行時に何を行うかをより適切に伝え、より正確な型を提供できるようになりました。
これに関する1つの注意点は、TypeScriptがこれらのリテラル型を解析するとき、適切なプリミティブ型のように見えるものを貪欲に解析しようとすることです。ただし、そのプリミティブのプリントバックが文字列の内容と一致するかどうかを確認します。つまり、TypeScriptは、文字列からプリミティブへの移動とその逆が一致するかどうかをチェックします。文字列が「ラウンドトリップ」できることがわからない場合は、基本プリミティブ型にフォールバックします。

三点目がパフォーマンスの向上です。 TypeScript4.8では、プロジェクト参照ビルドとともに、シナリオを高速化するいくつかの最適化が導入されています。 たとえば、TypeScriptは、モードno-op変更中にタイムスタンプの更新に時間を費やさないようにすることができるようになりました。 これにより、リビルドが高速になり、TypeScriptの出力を監視している可能性のある他のビルドツールを台無しにすることが回避されます。 かなり大規模な内部コードベースでは、多くの単純な一般的な操作で約10%~25%の時間短縮が見られ、 変更なしのシナリオでは約40%の時間短縮が見られました。TypeScriptコードベースでも同様の結果が見られました。

四点目が推論の改善です。 より適切な推論を行うために、TypeScriptがバインディングパターンから型を選択するのですが、2つの型がタプル型であるかどうかを判断する必要があります。タプル型があるかどうかを確認するためのヒントとして、既存の候補を探します。TypeScriptはバインディングpatternを認識するとtypeを作成し、そのtypeは優先度の低い候補として選択され、およびの型のヒントとしても使用されます。 タプルを生成する必要があることを示唆した場合においても、バインディングパターンに基づいて型引数を変更するべきではありません。
割り当てられているものに基づいて新しい配列のような値を突然呼び出すことはできないため、 バインディングパターンの型は生成される型に大きく影響します。
TypeScript4.8では、これらのバインドパターンが型引数の候補として使用されることはありません。 代わりに、この例のようにパラメーターがより具体的な型を必要とする場合にのみ参照されます。 古い動作に戻す必要がある場合は、いつでも明示的な型引数を指定できます。

五点目がファイル監視の修正です。 モードおよびエディターシナリオでの特定のファイル変更で、TypeScriptが非常に苦労するという長年のバグがありました。 場合によっては、再起動またはVS Codeが必要な古いエラーまたは不正確なエラーが症状として現れることがあります。これらはUnixシステムで頻繁に発生し、vimでファイルを保存したり、gitでブランチを交換したりした後に見たことがあるかもしれません。この原因は、Node.jsがファイルシステム全体で名前変更イベントを処理する方法の想定にありました。 LinuxとmacOSで使用されるファイルシステムはinodeを利用し、Node.jsはファイルウォッチャーをファイルパスではなくinodeにアタッチします。したがって、Node.jsがウォッチャーオブジェクトを返すとき、プラットフォームとファイルシステムに応じて、パスまたはinodeを監視している可能性があります。もう少し効率的にするために、TypeScriptは、パスがまだディスク上に存在することを検出した場合、同じウォッチャーオブジェクトを再利用しようとします。ファイルがそのパスにまだ存在していても、別のファイルが作成されている可能性があり、そのファイルには別のinodeがあるため、ここで問題が発生します。
そのため、TypeScriptは、新しいウォッチャーを元の場所にインストールする代わりに、ウォッチャーオブジェクトを再利用することになり、まったく無関係なファイルの変更を監視します。
JypeScript4.8はinodeシステムでこれらのケースを処理し、新しいウォッチャーを適切にインストールしてこれを修正します。
六点目がJavaScriptファイルです。 TypeScriptでは以前、 andexportステートメントで、値ではなく型で宣言されたエンティティをJavaScriptファイルでインポートおよびエクスポートすることができました。 存在しない値の名前付きインポートおよびエクスポートは、ECMAScriptモジュールで実行時エラーを引き起こすため、この動作は正しくありませんでした。
今回のアップデートにおいては、JavaScriptファイルがコメントの下またはコメントを介して型チェックされると、TypeScriptはエラーを発行するようになりました。

TypeScript4.7

TypeScript4.7のアップデートについて説明させていただきます。
一点目が新しいファイル拡張子です。新しいファイル拡張子を引き続き使用できるようになりました。ただし、指定したものとは異なるファイルを作成する必要がある場合があり、これらは常に明示的であることを好む場合もあります。さらにNode.jsは、これを支援する2つの拡張機能をサポートしています。
次に、TypeScriptは2つの新しいソースファイル拡張子をサポートします。 これらの拡張機能の使用は完全にオプションですが、主要なワークフローの一部として使用しないことを選択した場合でも役立てることができます。

二点目がモジュール検出の制御です。 JavaScriptへのモジュールの導入に関する問題は、既存の「スクリプト」コードと新しいモジュールコードの間のあいまいさが存在して点となります。 モジュール内のJavaScriptコードの実行方法はわずかに異なり、スコープルールも異なる点について注意が必要です。

三点目がエディターコマンドのサポートです。 これはGo To Definitionに似ていますが、宣言ファイル内に結果を返すことはありません。 代わりに、対応する実装ファイルを見つけようとし、そこで定義を見つけようとします。 これは、ファイル内の型宣言ではなく、ライブラリからインポートしている関数の実装を確認する必要がある場合に最も便利です。 この新しいコマンドは、Visual Studio Codeの最新バージョンで試すことができます。 場合によっては、TypeScriptはヒューリスティックを使用して、指定された定義の結果に対応するファイルを推測するため、これらの結果が不正確になる可能性があります。
Go To Implementationsは、さまざまなことを行うアルゴリズムとして機能し、コマンドは、どちらも周囲の結果を返さないという点で似ています。
ただしGo To Implementationsは内部でFind All Referencesを使用して何らかの型を満たす値を検索します。 Go To Source Definitionは、主に内部でGo To Definitionを使用します。これは、変数/プロパティをそれらの宣言まで、およびインポート/エクスポートを通じてトレースします。その変数/プロパティに存在する可能性のあるすべての値の起源を見つけようとはしない点が特徴となります。

まとめ

いかがでしたでしょうか? TypeScriptについて説明させていただきましたので、参考にしていただけましたら幸いです。