TypeScriptとは
TypeScriptは、JavaScriptのスーパーセットとして設計されたプログラミング言語です。マイクロソフトによって開発され、静的型付けを特徴としています。これにより、変数や関数の型を明示的に宣言することができ、開発時のエラーを早期に検出することが可能となります。TypeScriptは、JavaScriptのすべての機能を含みつつ、型安全性と大規模アプリケーションの開発を容易にするための追加機能を提供します。これにより、コードの品質と保守性が向上し、開発者の生産性も高まります。
※スーパーセット・・・元の言語との互換性を保ちつつ、元の言語を拡張して作った言語のことを指します。TypeScriptは、JavaScriptとの互換性を保ちつつ、JavaScriptを拡張して作った言語です。
コンパイル
TypeScriptは、ブラウザやNode.jsで直接実行することができないため、実行する前にJavaScriptに変換する必要があります。この変換のプロセスをコンパイルと言います。
コンパイルの際、TypeScriptコードはJavaScriptコードに変換され、型チェックやその他の検査も同時に行われます。
型注釈
変数などに対して明示的に型をつけることを型注釈と言います。
const message: string = "Hello World";
function add(x: number, y: number): number {
return x + y;
}
型推論
一方で型宣言を省略し、代入された値から型を推測してくれることを型推論と言います。
const message = "Hello World";
function add(x, y) {
return x + y;
}
基本的な文法
プリミティブ型
- boolean:真偽値
- number:数値
- string:文字列
- bigint:大きな整数
- symbol:一意の値を示す
- undefind:値が定義されていない状態を示す
- null:値が存在しない状態を示す
const isReturn: boolean = false;
const age: number = 10;
const name: string = "山田太郎";
const bigNumber: bigint = 100n;
const uniqueNumber: symbol = Symbol("unique");
const notNumber: undefind = undefind;
const empty: null = null;
特殊な型
- any:何でも代入できる型です。型が不明な場合や、動的に型が決まる値を扱うときに使用します。ただし、any型を使うと型チェックが無効化され、型の安全性が低下するため、必要な場合に限定して使うことが推奨されています
let value: any;
value = 123;
value = "Hello";
value = true;
- unknown:any型と似て、何でも代入できる型です。しかし、unknown型に対しては、具体的な型が判明するまで操作が制限されます。これにより、型の安全性が保たれます
let value: unknown;
value = 42;
value = "Hello, world!";
value = { name: "Alice" };
// 直接の操作はできない(コンパイルエラーになる)
value.foo(); // コンパイルエラー
value.toUpperCase(); // コンパイルエラー
// 型チェック後に操作可能
if (typeof value === "string") {
console.log(value.toUpperCase()); // OK
}
if (typeof value === "object" && value !== null) {
console.log((value as { name: string }).name); // OK
}
- void:値が存在しないことを示す型です。主に、何も返さない関数の戻り値として使用されます
function logMessage(message: string): void {
console.log(message);
}
- never:決して何も返さないことを示す型です。エラーを投げる関数や、無限ループの関数の戻り値として使用されます
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
- literal:指定した型の特定の値しか代入できない型です。リテラル型を使うと、特定の文字列や数値などの値を限定することができます
let direction: "up" | "down";
direction = "up"; // OK
direction = "left"; // エラー
-
object:オブジェクト型で、基本的に
{}
を使って型アノテーションを行います。プロパティの型を明示的に指定することで、オブジェクトの構造を定義できます
let person: { name: string; age: number };
person = { name: "John", age: 30 };
-
array:配列の型定義には、
T[]
構文とArray<T>
構文の2つがあります。どちらも同じ意味ですが、状況に応じて使い分けられます
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];
- tuple:要素数と型が固定された配列です。要素ごとに異なる型を指定できるため、決まった構造のデータを扱う場合に有効です
let tuple: [string, number];
tuple = ["hello", 42]; // OK
tuple = [42, "hello"]; // エラー
-
union:
|
を利用して複数の型を許容する変数を作成できます。これにより、変数が複数の型を持つことができます
let id: number | string;
id = 123; // OK
id = "ABC123"; // OK
- enum:関連する一連の数値または文字列値の集まりを定義するための型です。複数の選択肢がある値を管理する場合に便利です
enum Direction {
Up = 1,
Down,
Left,
Right
}
let dir: Direction = Direction.Up;
型エイリアス
型エイリアスは、TypeScriptで複雑な型に対してわかりやすい名前をつけるために使用します。これにより、再利用可能なカスタム型を定義でき、コードの可読性と保守性が向上します。
type UserID = string | number;
let user1: UserID = "abc123";
let user2: UserID = 987654321;
type Point = {
x: number;
y: number;
};
let p: Point = { x: 10, y: 20 };
インターフェース
インターフェースは、オブジェクトの構造を定義するために使用します。型エイリアスと似ていますが、インターフェースはプロパティやメソッドの設計図を定義するのに特化しており、オブジェクト指向プログラミングでよく使われます。また、インターフェースは継承が可能で、複数のインターフェースを組み合わせることもできます。
interface Person {
name: string;
age: number;
greet(): void;
}
let user: Person = {
name: "Alice",
age: 25,
greet() {
console.log("Hello, " + this.name);
}
};
user.greet(); // "Hello, Alice"
オプショナルプロパティ
オプショナルプロパティは、インターフェースや型エイリアスで定義されるプロパティが、必須ではないことを示すために使用します。プロパティ名の後に ? を付けることで、そのプロパティがオプションであることを明示します。これにより、プロパティが存在しないオブジェクトを許容することができます。
interface Product {
name: string;
price: number;
description?: string; // オプショナルプロパティ
}
let item1: Product = {
name: "Laptop",
price: 1500
};
let item2: Product = {
name: "Phone",
price: 800,
description: "Latest model"
};