TypeScriptとは
TypeScriptはJavaScriptのスーパーセットとして設計されたプログラミング言語です。JavaScriptの全機能を継承しつつ、静的型付けシステムを導入することで、大規模アプリケーションの開発をより安全かつ効率的にします。コンパイル時に型チェックを行うため、実行前に多くのエラーを検出できます。
基本的なデータ型
TypeScriptでは、変数宣言にvar、let、constが使用できますが、スコープの問題を避けるため、通常はletとconstを推奨します。
let counter = 10;
let emptyValue: undefined = undefined;
// constは定数を宣言し、初期化後に値を変更できません
const maxNumber: number = 100;
変数とデータ型
TypeScriptはJavaScriptのデータ型を継承し、さらにいくつかの型を追加しています。主なデータ型を見ていきましょう。
1. boolean
論理値を表し、trueとfalseの2つの値を取ります。
let isActive: boolean = true;
2. number
整数と浮動小数点数を表します。
const price: number = 19.99;
3. string
単一引用符'、二重引用符"、またはバッククォート`で文字列を表現します。バッククォートは複数行文字列や式の埋め込みに使用できます。
let currentYear: string = "2023年";
let greeting: string = `こんにちは、今は${currentYear}です`;
4. 配列 Array
型名[]または配列ジェネリックArray<要素型>で表現します。
let numbers: number[] = [10, 20, 30];
let moreNumbers: Array<number> = [40, 50, 60];
numbers.push(70) // 末尾に追加
numbers.unshift(0) // 先頭に挿入 0 10 20 30 70
numbers.pop() // 末尾を削除 0 10 20 30
numbers.splice(1,2) // 指定位置から指定数削除 0 30
numbers.shift() // 先頭を削除 30
numbers = numbers.concat(moreNumbers) // 配列を結合
numbers.indexOf(50) // 要素の最初の出現位置を検索
numbers.sort() // ソート
numbers.reverse() // 配列の順序を反転
5. タプル Tuple
要素数と各要素の型が固定された配列を表します。
let userInfo: [string, number];
userInfo = ['Taro', 25]; // 正しい
userInfo = [30, 'Jiro']; // エラー
6. 列挙型 enum
関連する定数の集合を定義します。
enum Status {Pending, Approved, Rejected}
let applicationStatus: Status = Status.Approved; // 1 デフォルトでは0から始まる
enum Status {Pending = 1, Approved = 2, Rejected = 3} // メンバーの値を手動で指定も可能
7. any
任意の型の値を代入できる変数を宣言します。
let flexibleVar: any = 42;
flexibleVar = "文字列にも変更可能";
8. void
型がないことを表し、主に関数が値を返さない場合に使用します。
function showMessage(): void {
console.log("メッセージを表示");
}
9. nullとundefined
nullはオブジェクト値が欠如していることを、undefinedは値が未定義であることを表します。
let nullValue: null = null;
let undefinedValue: undefined = undefined;
10. neverとobject
neverは決して発生しない値の型を、objectはプリミティブ型でない型を表します。
let errorObject: object = {};
条件分岐とループ
1. 条件分岐
if…else if…else
if(score > 80) {
console.log("優秀です")
} else if(score > 60) {
console.log("合格です")
} else {
console.log("不合格です")
}
switch…case
switch(color) {
case "red": {
console.log("赤色");
break;
}
case "blue": {
console.log("青色");
break;
}
default: {
console.log("その他の色");
break;
}
}
三項演算子
let result = age >= 20 ? "成人" : "未成年"
console.log(result) // 年齢に応じて結果が変わる
2. ループ処理
for ループ
for(let i = 1; i <= 5; i++) {
console.log(i);
}
for…in ループとfor…of ループ
// for..in はインデックスを反復処理
let word:any="hello"
for(let index in word) {
console.log(index) //0 1 2 3 4
console.log(word[index]) //h e l l o
}
// for..of は要素を反復処理
let items= [1, "text", true];
for (let element of items) {
console.log(element); // 1, "text", true
}
while ループとdo…while ループ
let count=5
while(count > 0) {
count--;
console.log(count)// 4 3 2 1 0
}
let value=5
do {
console.log(value); // 5 4 3 2 1
value--;
} while(value > 0);
関数
TypeScriptでは、関数のパラメータ型と戻り値の型を指定できます。戻り値の型は省略可能で、TypeScriptが自動的に推論します。
通常の関数
function multiply (num1:number, num2: number): number {
return num1 * num2
}
匿名関数(関数式)
const divide=function(num1:number, num2: number): number{
return num1 / num2
}
アロー関数
const subtract = (num1:number, num2: number): number => {
return num1 - num2
}
パラメータの種類
- オプションパラメータ:パラメータ名後に
?を付けて定義 - デフォルトパラメータ:デフォルト値を持つパラメータ
- 残余パラメータ:不特定数のパラメータ
function createFullName(firstName: string, lastName?: string): void {
console.log(`名前: ${firstName} ${lastName || ''}`)
}
function greet(name: string, greeting = "こんにちは"): void {
console.log(`${greeting}、${name}さん!`)
}
function concatenate(separator: string, ...strings: string[]) {
return strings.join(separator);
}
クラス
クラスはユーザー定義のデータ型で、プロパティとメソッドを持ちます。TypeScriptではclassキーワードでクラスを定義し、newでインスタンス化します。staticキーワードは静的メンバー(プロパティとメソッド)を定義し、これらはクラス自体に存在し、クラス名.メンバー名で呼び出します。
class Vehicle {
static description: string = "これはVehicleクラスです"
brand: string;
constructor(brand: string) {
this.brand = brand;
}
static displayInfo(): void {
console.log(Vehicle.description);
}
drive(): void {
console.log(`${this.brand}の車を運転中です。`);
}
}
let car = new Vehicle('Toyota');
car.drive(); // Toyotaの車を運転中です。
Vehicle.displayInfo(); // これはVehicleクラスです
継承
TypeScriptは一度に1つのクラスしか継承できません(多重継承はサポートしていません)。クラスの継承にはextendsキーワードを使用します。superキーワードは親クラスへの参照です。
class ElectricCar extends Vehicle {
drive() {
super.drive();// 親クラスのメソッドを呼び出し
console.log('静かで環境に優しい運転です!');
}
}
let tesla = new ElectricCar('Tesla');
tesla.drive() // Teslaの車を運転中です。静かで環境に優しい運転です!
抽象クラス
抽象クラス自体はインスタンス化できませんが、他の派生クラスの基底クラスとして使用でき、派生クラスは抽象メソッドを実装する必要があります。abstractキーワードで抽象クラスと抽象メソッドを定義します。
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('動物が動いています...');
}
}
カプセル化
TypeScriptではアクセス修飾子とゲッター/セッターの設定により、クラスをカプセル化できます。
public:デフォルト、どこからでもアクセス可能protected:クラス自身とそのサブクラスからアクセス可能private:定義されたクラス内のみアクセス可能
class Employee {
private _salary: number;
constructor(salary: number) {
this._salary = salary;
}
set salary(newSalary: number) {
if (newSalary > 0) {
this._salary = newSalary;
}
}
get salary(): number {
return this._salary;
}
}
let employee = new Employee(50000);
employee.salary = 60000
console.log(employee.salary); // 60000
インターフェース
インターフェースはinterfaceキーワードで定義し、implementsキーワードで実装します。1つのクラスは複数のインターフェースを同時に実装できます。
interface Flyable {
fly(): void;
}
class Bird extends Animal implements Flyable {
makeSound(){
console.log("鳴き声");
}
fly(){
console.log("空を飛んでいます");
}
}
let sparrow = new Bird();
sparrow.fly()
モジュール
通常、コードは必要に応じて複数のファイル(モジュール)に分割されます。モジュール内で定義された変数、関数、クラスなどはモジュール外からは見えず、exportでエクスポートする必要があります。対応して、importでインポートできます。
// utils.ts
export function formatDate(date: Date): string {
return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`;
}
// app.ts
import { formatDate } from './utils';
console.log(formatDate(new Date()));
ジェネリック
ジェネリックを使用すると、関数、クラス、インターフェースなどを定義する際に、具体的な型ではなくプレースホルダーを使用して型を表現できます。
function createPair<S, T>(first: S, second: T): [S, T] {
return [first, second];
}
let pair = createPair<string, number>("answer", 42); // 型パラメータはstringとnumber
let anotherPair = createPair(true, false); // コンパイラがSとTをbooleanと推論