最近のWebアプリケーション開発ではTypeScriptを採用することが増えています。従来のJavaScriptとは何が違うのか、どういった利点があるのかを紹介します。
TypeScriptとは
TypeScriptはMicrosoftによって開発がはじまったプログラミング言語になります。プログラミング言語といっても、TypeScriptの実行環境があるわけではなく、TypeScriptからJavaScriptに変換した上で実行されます。つまりJavaScriptが基本です。
そしてJavaScriptに型付け機能や、モダンな仕様を先進的に取り込んだのがTypeScriptになります。
TypeScriptはJavaScriptのスーパーセット
TypeScriptはJavaScriptのスーパーセットと言われます。このスーパーセットとは、JavaScriptの仕様をすべて内在しているという意味になります。その上で、独自の機能を追加したのがTypeScriptです。
既存のJavaScriptプロジェクトをTypeScript対応するのはとても簡単です。 .js
になっている拡張子を .ts
に変えるだけで済みます。もちろん、そのままでは型指定がないといったエラーになりますが、エラーを無視すれば動作させられます。このようにJavaScriptの機能をすべて使えるのがスーパーセットたる所以です。
TypeScriptの主な機能
型
TypeScriptは名前の通り、型(タイプ)指定できるのが最大の魅力になります。もともとMicrosoftがTypeScriptを作るきっかけになったのも、型指定がないことで大規模なアプリケーション開発が困難であるという点にあります。
型指定がないことで柔軟に開発できるのがJavaScriptの魅力ですが、チームによる開発時には型指定がないことで予期せぬ動作につながる恐れがあります。引数に文字列を指定すればいいのか、数値を指定すればいいのか、テキストで書いておくことはできます。しかし、開発者はそれを無視したり読まずにプログラミングできてしまいます。TypeScriptではあらかじめ型を指定することで、コーディング中にエラーや警告を表示できます。
これは外部の開発者が作ったライブラリを利用する際には特に有効でしょう。どういった引数を与えれば良いのか明示されており、返却値の型も分かっていれば安心して開発できます。
モダンな仕様
TypeScriptのもう一つの魅力が、先進的なAPIを先んじて取り込んでいたことです。アロー関数やlet/const、テンプレート文字列などはECMAScript 6が標準化する前に実現していました。TypeScriptのトランスパイラーが、標準のJavaScriptに変換する際にこれらの機能を使ったコードを変換してくれます。
現在ではECMAScript 6が標準になっていますので、多くの機能は標準のJavaScriptで実現できています。他にも独自の機能追加としてインタフェースや名前空間なども用意されています。
最近のアップデート
執筆時点(2023年9月)での最新版は5系(5.2)となっています。5系では次のような機能が追加されています。
const型パラメーター
引数でconstを指定できるようになります。これによって、変更されないことが保証されます。
type HasNames = { names: readonly string[] };
declare function fnBad<const T extends string[]>(args: T): void;
function getNamesExactly<const T extends HasNames>(arg: T): T["names"] {
return arg.names;
}
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
// ↓ constで返ってきているので、 string[] には適用できない
fnBad(["a", "b" ,"c"]);type HasNames = { names: readonly string[] };
declare function fnBad<const T extends string[]>(args: T): void;
function getNamesExactly<const T extends HasNames>(arg: T): T["names"] {
return arg.names;
}
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
// ↓ constで返ってきているので、 string[] には適用できない
fnBad(["a", "b" ,"c"]);
デコレーター
デコレーターはクラスやメソッドなどにアタッチできる機能です。メソッドの挙動を変えたり、クラスを自動で継承にしたりできます。Pythonなどではすでに実現されている機能です。
function loggedMethod(originalMethod: any, _context: any) {
return funtion(this: any, ...args: any[]) {
console.log("LOG: Entering method.")
const result = originalMethod.call(this, ...args);
console.log("LOG: Exiting method.")
return result;
}
}
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
@loggedMethod
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
const p = new Person("Ron");
p.greet();
// Output:
//
// LOG: Entering method.
// Hello, my name is Ron.
// LOG: Exiting method.function loggedMethod(originalMethod: any, _context: any) {
return funtion(this: any, ...args: any[]) {
console.log("LOG: Entering method.")
const result = originalMethod.call(this, ...args);
console.log("LOG: Exiting method.")
return result;
}
}
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
@loggedMethod
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
const p = new Person("Ron");
p.greet();
// Output:
//
// LOG: Entering method.
// Hello, my name is Ron.
// LOG: Exiting method.
enum型の引数
enum型を引数の型に指定することで、その範囲でのみ引数を受け付けるようになります。
enum E {
Foo = 10,
Bar = 20,
}
function takeValue(e: E) {}
takeValue(E.Foo); // OK
takeValue(123); // Errorenum E {
Foo = 10,
Bar = 20,
}
function takeValue(e: E) {}
takeValue(E.Foo); // OK
takeValue(123); // Error
usingの追加
これまでの変数宣言は var/let/constの3種類でしたが、さらに追加で using が入ります。これは、変数がスコープ外になった時に Symbol.dispose
メソッドが呼ばれます。ファイルなどで不要になったタイミングで呼び出すといったことを想定しているようです。
async/await と組み合わせて、 await using
も用意されています。
const V = () => ({
[Symbol.dispose]() {
console.log("不要");
}
});
{
console.log("変数定義前");
using v = V();
console.log("変数利用中");
}
console.log("変数利用終了");const V = () => ({
[Symbol.dispose]() {
console.log("不要");
}
});
{
console.log("変数定義前");
using v = V();
console.log("変数利用中");
}
console.log("変数利用終了");
TypeScriptの使い方
TypeScriptを一番簡単に使えるのはNode.jsのTypeScriptをインストールすることでしょう。そして、まず設定ファイルを生成します。
$ npm i typescript -D
そうすれば tsc
コマンドが使えるようになります。まず設定ファイルの tsconfig.json
作成します。
$ npx tsc --init
設定ファイルでは細かく指定できますが、まずはそのままで大丈夫です。
コードを書きます。ファイル名は index.ts とします。
function Hello(name: string) {
console.log(`Hello ${name}`);
}
Hello('Hexabase');function Hello(name: string) {
console.log(`Hello ${name}`);
}
Hello('Hexabase');
ファイルを作成したら、トランスパイルします。
$ npx tsc index.ts
そしてできあがったindex.jsを実行します。
$ node index.js
Hello Hexabase$ node index.js
Hello Hexabase
これが基本的な流れになります。もし変換から実行という流れが面倒であれば、 ts-node
をインストールすると良いでしょう。
$ npm i ts-node -D
そうすれば、 ts-node
コマンドでTypeScriptファイルを直接実行できます。
% npx ts-node index.ts
Hello Hexabase% npx ts-node index.ts
Hello Hexabase
学習リソース
TypeScriptを学ぶのに良いリソースを紹介します。
TypeScript: TS Playground
TypeScriptの公式サイトに用意されているプレイグラウンドです。各バージョンごとにTypeScriptを実際に記述して、その結果を確認できます。
TypeScript の使用を開始する – Training | Microsoft Learn
Microsoft Learnに用意されているTypeScript学習コンテンツです。全部で36分程度、全部で8つのセッションに分かれています。
TypeScript入門 (全19回) – プログラミングならドットインストール
ドットインストールのTypeScript入門です。4回までを無料視聴できます。全19回、クラスの継承やインタフェース、ジェネリクスなどについても学べます。
まとめ
今後、Webアプリケーション開発時にTypeScriptが採用されるケースは増えていくはずです。そのためにもフロントエンドエンジニアであれば、TypeScriptを学んでおくことは必須になるでしょう。
さらにTypeScriptは次々と進化しており、便利な機能が増えています。新しい情報を積極的に取り入れて、より良いコードを書けるようになりましょう。
TypeScript: JavaScript With Syntax For Types.
役に立ったら、記事をシェアしてください