読み込み中...

【TypeScript】比較演算子を完全マスターする10選の実例コード

TypeScriptの比較演算子の使い方を視覚的に理解するイラスト TypeScript
この記事は約23分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

TypeScriptは、JavaScriptのスーパーセットとして広く認識されていますが、型システムが強化されているため、より安全で効率的なコードの記述が可能となります。

特に、比較演算子を用いたときの動作は、型によって異なる場合があるため、正確な理解が求められます。

この記事では、TypeScriptでの比較演算子の使用方法を、基本的な使い方から応用例、そして注意点まで、サンプルコードを交えながら詳しく解説します。

初心者の方でも安心して理解できるように、実行結果も詳しく説明していますので、最後まで読んでいただくことで、比較演算子の使い方を完全にマスターすることができるでしょう。

●TypeScriptの比較演算子とは

比較演算子は、2つの値や変数の関係を評価するための演算子です。

JavaScriptと同様に、TypeScriptでも「==」や「===」などの比較演算子を使用することができますが、TypeScriptには型が関与するため、いくつかの注意点が存在します。

○基本的な比較演算子の種類とその意味

TypeScriptで使用できる基本的な比較演算子のリストとその意味を紹介します。

  • ==:値が等しい
  • !=:値が等しくない
  • ===:値と型が等しい(厳密等価)
  • !==:値と型が等しくない(厳密不等価)
  • <:より小さい
  • <=:以下
  • >:より大きい
  • >=:以上

こちらはあくまで基本的なもので、TypeScriptの特徴や型システムを理解する上で、特に=====の違いは非常に重要です。

この点については、後ほど詳しく解説していきます。

●比較演算子の使い方

比較演算子の使い方を理解するため、実際のサンプルコードを通して説明します。

○サンプルコード1:数値の比較

このコードでは、数値の比較を行っています。

2つの変数num1num2の値を比較し、結果をコンソールに出力しています。

let num1: number = 10;
let num2: number = 20;

console.log(num1 < num2);  // trueを出力

この例では、num1の値がnum2の値より小さいため、trueという結果がコンソールに出力されます。

次に進む前に、このサンプルコードの実行結果を考えてみましょう。

正確には、num1の値が10、num2の値が20であるため、num1 < num2の評価結果はtrueとなります。

○サンプルコード2:文字列の比較

このコードでは、文字列の比較を行っています。

2つの変数str1str2の値を比較し、結果をコンソールに出力しています。

let str1: string = "apple";
let str2: string = "banana";

console.log(str1 < str2);  // trueを出力

この例では、文字列の比較では辞書的な順序(文字コードの順)で比較されます。

そのため、applebananaより前にくるため、trueという結果がコンソールに出力されます。

上記のサンプルコードを実行すると、str1が”apple”、str2が”banana”であるため、str1 < str2の評価結果はtrueとなります。

○サンプルコード3:Booleanの比較

このコードでは、Booleanの値を比較しています。

2つの変数bool1bool2の値を比較し、結果をコンソールに出力しています。

let bool1: boolean = false;
let bool2: boolean = true;

console.log(bool1 == bool2);  // falseを出力

この例では、bool1の値がfalsebool2の値がtrueであるため、2つの値は等しくありません。

その結果、falseという結果がコンソールに出力されます。

このサンプルコードを実行すると、bool1bool2の評価結果は等しくないため、falseという結果が出力されます。

●TypeScriptでの比較演算子の応用例

TypeScriptの比較演算子は基本的な使い方だけでなく、多岐にわたる応用が期待されます。

ここでは、配列内の要素の比較という応用例を紹介します。その際のサンプルコードと、その実行結果を中心に解説していきます。

○サンプルコード4:配列内の要素比較

TypeScriptでは配列内の要素を直接比較する際に、比較演算子を活用することができます。

下記のコードでは、二つの配列が持つ要素を1つずつ比較し、全ての要素が同じかどうかを確認する関数を表しています。

function 配列要素の比較(arr1: number[], arr2: number[]): boolean {
  // 配列の長さが異なる場合、falseを返す
  if (arr1.length !== arr2.length) {
    return false;
  }

  // 同じ長さの場合、各要素を比較
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] !== arr2[i]) {
      return false;
    }
  }
  return true;
}

const arrA = [1, 2, 3];
const arrB = [1, 2, 3];
const arrC = [1, 2, 4];

console.log(配列要素の比較(arrA, arrB));  // true
console.log(配列要素の比較(arrA, arrC));  // false

このコードでは、配列要素の比較関数を使ってarrAarrBarrAarrCの要素を比較しています。

この例では、arrAarrBの要素は完全に一致しているため、trueが返されます。

一方、arrAarrCは最後の要素が異なるため、falseが返されます。

このように、配列の要素ごとの比較は繰り返し文と比較演算子を組み合わせることで容易に行えます。

しかし、この方法はプリミティブなデータ型の要素に対してのみ有効です。

オブジェクトを要素とする配列の比較には、さらなる工夫が必要となります。

○サンプルコード5:オブジェクトのプロパティ比較

TypeScriptでは、オブジェクトのプロパティ間での比較も一般的に行われます。

しかし、オブジェクトの比較には特別な注意点がいくつか存在します。

ここでは、オブジェクトのプロパティ同士を安全に比較する方法をサンプルコードを用いて解説します。

まず、オブジェクトのプロパティ比較の基本から見ていきましょう。

このコードでは、二つのオブジェクトpersonApersonBを使って、各プロパティが等しいかどうかを比較するコードを表しています。

この例では、nameageというプロパティをもつオブジェクトの比較をしています。

const personA = {
    name: "太郎",
    age: 25
};

const personB = {
    name: "太郎",
    age: 30
};

// nameプロパティの比較
if (personA.name === personB.name) {
    console.log("名前が同じです。");
} else {
    console.log("名前が異なります。");
}

// ageプロパティの比較
if (personA.age === personB.age) {
    console.log("年齢が同じです。");
} else {
    console.log("年齢が異なります。");
}

このサンプルコードを実行すると、「名前が同じです。」と「年齢が異なります。」という結果がコンソールに表示されます。

これはpersonApersonBnameプロパティは同じ値であるため、名前の比較が真となりますが、ageプロパティは異なる値であるため、年齢の比較が偽となるためです。

次に、オブジェクトのプロパティ比較における注意点を考慮しながら、さらに高度な比較を行う方法を見ていきましょう。

このコードでは、personCpersonDという二つのオブジェクトを使って、深い階層のプロパティが等しいかどうかを比較するコードを表しています。

この例では、addressというオブジェクトの中にcityzipcodeというプロパティが存在し、これらのプロパティを比較しています。

const personC = {
    name: "花子",
    age: 27,
    address: {
        city: "東京",
        zipcode: "100-0001"
    }
};

const personD = {
    name: "花子",
    age: 27,
    address: {
        city: "東京",
        zipcode: "100-0002"
    }
};

// addressプロパティのcityの比較
if (personC.address.city === personD.address.city) {
    console.log("住所の都市が同じです。");
} else {
    console.log("住所の都市が異なります。");
}

// addressプロパティのzipcodeの比較
if (personC.address.zipcode === personD.address.zipcode) {
    console.log("郵便番号が同じです。");
} else {
    console.log("郵便番号が異なります。");
}

このコードを実行すると、「住所の都市が同じです。」と「郵便番号が異なります。」という結果が得られます。

これは、personCpersonDaddress.cityプロパティが同じ値を持っている一方で、address.zipcodeプロパティが異なる値を持っているためです。

オブジェクトのプロパティ比較は、プロパティの階層が深い場合や、比較したいプロパティの数が多い場合には、特に注意が必要です。

プロパティが存在しない場合にアクセスしようとするとエラーが発生するため、存在チェックを行うなどの対策が必要です。

○サンプルコード6:条件式内での活用

TypeScriptの比較演算子は、特定の条件が満たされているかどうかを判断するためのものです。

例として、ある数値が特定の範囲内にあるかどうか、ある文字列が特定の文字列と一致しているかどうかなど、多岐にわたる場面で使用されます。

特に、条件式の中での活用は非常に頻繁に見られます。条件式は、ある条件が真か偽かによって、異なる処理を行うためのもので、TypeScriptではif文や三項演算子などで実現されます。

このコードでは、ageという変数を使って、成人か未成年かを判定するコードを表しています。

この例では、ageが20以上であれば「成人」と判定し、20未満であれば「未成年」と判定しています。

const age = 18;

// ageが20以上かどうかを判断
if (age >= 20) {
    console.log("成人です。");
} else {
    console.log("未成年です。");
}

このコードを実行すると、18歳は20歳未満であるため、「未成年です。」と表示されます。

しかし、条件式の中では、複数の条件を組み合わせることも多いです。

例えば、ある商品が特定の価格帯に入っているかどうか、特定のキーワードが含まれているかどうかなど、複数の条件を組み合わせて判断することがあります。

以下のコードでは、pricekeywordという変数を使って、商品が特定の条件を満たしているかどうかを判断するコードを紹介しています。

この例では、価格が1000円以上3000円以下であり、かつキーワードに「SALE」という文字列が含まれているかどうかを判断しています。

const price = 2500;
const keyword = "SUMMER SALE";

// 価格とキーワードの両方の条件を判断
if (price >= 1000 && price <= 3000 && keyword.includes("SALE")) {
    console.log("特別セールの商品です。");
} else {
    console.log("通常の商品です。");
}

このコードを実行すると、価格が1000円以上3000円以下であり、かつキーワードに「SALE」という文字列が含まれているため、「特別セールの商品です。」と表示されます。

条件式内での比較演算子の活用は、日常的に多くの場面で使われるので、これをしっかりと理解しておくことは非常に重要です。

特に、複数の条件を組み合わせた複雑な判定を行う場面では、正確なロジックを構築するための基盤となります。

○サンプルコード7:関数の戻り値との比較

TypeScriptでは、関数の戻り値を比較演算子で評価することが可能です。

特定の条件下で関数の戻り値が期待する値と一致するか、あるいはその逆の場合に動作を分岐させたいとき、この方法は非常に役立ちます。

// 年齢を取得する関数
function getAge(): number {
    return 25;
}

// 年齢が成人かどうかを判定する関数
function isAdult(age: number): boolean {
    return age >= 20;
}

// getAgeの戻り値を利用して成人かどうかを確認
if (isAdult(getAge())) {
    console.log("成人です。");
} else {
    console.log("未成年です。");
}

このコードでは、getAge関数で年齢を取得し、その戻り値をisAdult関数に渡して成人かどうかを判定しています。

この例ではgetAgeの戻り値が25なので、「成人です。」と出力されます。

しかし、関数の戻り値を直接比較する場合には注意も必要です。

特に、関数の中で非同期処理を行っている場合や、外部のデータを参照している場合など、関数の戻り値が常に一定であるとは限らないためです。

また、関数の戻り値を比較する際には、型の一致も考慮する必要があります。

function getStringNumber(): string {
    return "25";
}

if (getAge() === getStringNumber()) {
    console.log("一致します。");
} else {
    console.log("一致しません。");
}

上記のコードでは、getAge関数の戻り値とgetStringNumber関数の戻り値を比較していますが、一方は数値、もう一方は文字列という異なる型を持っているため、「一致しません。」と出力されます。

このように、関数の戻り値の型を正確に理解して、適切な比較方法を選択することが重要です。

応用として、関数の戻り値を変数に格納してから比較することも考えられます。

この方法を取ることで、比較を行う前に戻り値の内容をチェックしたり、加工したりすることが容易になります。

const age = getAge();
const stringAge = getStringNumber();

if (age.toString() === stringAge) {
    console.log("一致します。");
} else {
    console.log("一致しません。");
}

この例では、getAgeの戻り値を文字列に変換してから、getStringNumberの戻り値と比較しています。

このように変数を利用することで、より複雑な条件での比較も簡単に行うことができます。

○サンプルコード8:型ガードの活用

TypeScriptはJavaScriptに型システムを導入しており、そのため変数や関数の引数、戻り値の型を明示的に定義できます。

この特性を活かし、特定の型であるかどうかを確認する「型ガード」というテクニックが使われます。

このコードでは、型ガードを使って異なる型のデータを取り扱うコードを表しています。

この例では、動物の名前を取得する関数を作成していますが、その動物が魚である場合と鳥である場合で取得する名前の方法が異なります。

interface 魚 {
    泳ぐ: () => void;
    名前: string;
}

interface 鳥 {
    飛ぶ: () => void;
    名前: string;
}

function 名前を取得(動物: 魚 | 鳥) {
    // 型ガードの活用
    if ('泳ぐ' in 動物) {
        // こちらは魚の名前を返す
        return 動物.名前;
    } else {
        // こちらは鳥の名前を返す
        return 動物.名前;
    }
}

const マグロ: 魚 = {
    泳ぐ: () => console.log('泳ぐマグロ'),
    名前: 'マグロ'
};

const スズメ: 鳥 = {
    飛ぶ: () => console.log('飛ぶスズメ'),
    名前: 'スズメ'
};

console.log(名前を取得(マグロ)); // マグロ
console.log(名前を取得(スズメ)); // スズメ

このコードを実行すると、名前を取得関数は、与えられた動物のオブジェクトがの型である場合との型である場合で、適切な名前を返す動作をします。

このように、TypeScriptの型ガードは、特定の型が保証されるスコープ内で、その型のプロパティやメソッドに安全にアクセスできるようになります。

また、実行結果として、マグロとスズメという名前がそれぞれコンソールに出力されることを期待しています。

このように型ガードは、複数の異なる型を持つ変数やオブジェクトを扱う際に、特定の型のプロパティやメソッドに安全にアクセスするための非常に便利な方法と言えるでしょう。

○サンプルコード9:nullとundefinedの比較

TypeScriptを使用する際、nullとundefinedの扱いは非常に重要です。

両者は異なる存在であるにもかかわらず、多くの初心者がこの2つの違いについて混乱してしまいます。

ここでは、これら2つの値をどのように比較するか、またその背景にある違いについて解説します。

このコードでは、nullとundefinedを比較しています。

この例では、それぞれを等価演算子(==)と厳密等価演算子(===)で比較し、その結果をconsole.logで出力しています。

let valueNull: null = null;
let valueUndefined: undefined = undefined;

// ==での比較
console.log(valueNull == valueUndefined); // true
// ===での比較
console.log(valueNull === valueUndefined); // false

上記のコードを実行すると、初めの比較でtrueが、次の比較でfalseが出力されます。

これは、==は型変換を行って比較するため、nullとundefinedは等しいと評価されます。

一方、===は厳密な比較を行い、型変換をせずに比較するため、nullとundefinedは等しくないと評価されます。

このことから、TypeScriptやJavaScriptでnullとundefinedを比較する際は、どの比較演算子を使用するかに注意が必要です。

特に、意図しない型変換を避けるため、厳密等価演算子(===)の使用を推奨します。

また、nullとundefinedの違いについて簡単に触れておくと、nullは「値が存在しない」という意味を持ち、undefinedは「値がまだ定義されていない」という意味を持っています。

この違いを理解しておくことは、エラーのトラブルシューティングやコードの可読性向上に役立ちます。

応用例として、関数の戻り値やオプショナルなプロパティの扱いにもnullとundefinedは関わってきます。

例えば、関数が特定の条件下で値を返さない場合、戻り値としてnullを指定することができます。

また、オプショナルなプロパティはundefinedとして扱われるため、これらの違いをしっかりと理解しておくことで、より柔軟なコードを書くことが可能となります。

function findUserById(id: number): string | null {
    if (id === 1) {
        return "Taro";
    }
    return null;
}

interface UserProfile {
    name: string;
    age?: number; // オプショナルなプロパティ
}

const user: UserProfile = {
    name: "Hanako"
};

console.log(user.age); // undefined

上記のコードでは、関数findUserByIdはidが1の場合、文字列を返し、それ以外の場合はnullを返すようになっています。

また、UserProfileインターフェースにはオプショナルなプロパティageがあり、このプロパティが指定されていない場合、undefinedとして扱われることが示されています。

○サンプルコード10:型アサーションを活用した比較

TypeScriptでは、特定の変数やオブジェクトが特定の型であると宣言したい場面があります。

このような場合には「型アサーション」という技術を使用します。

型アサーションは、開発者がTypeScriptの型チェッカーよりもその変数の型に関してもっと知っていると主張するためのものです。

ここでは、型アサーションを使って変数の型を宣言し、その後に比較演算子を使用して値を比較する方法を詳細に解説します。

このコードでは型アサーションを使って、変数の型を明示的に宣言しています。

この例では、変数valueany型として宣言されているため、その真の型が何であるかTypeScriptは知りません。

そこで、型アサーション<string>を使用して、valueが実際にはstring型であることをTypeScriptに伝えます。

その後で、valueを他の文字列と比較しています。

let value: any = "TypeScriptは素晴らしい!";

// 型アサーションを使用してvalueがstring型であると宣言
let assertedValue: string = <string>value;

if (assertedValue === "TypeScriptは素晴らしい!") {
    console.log("型アサーションが正しく動作しています。");
} else {
    console.log("何かがおかしい...");
}

上記のコードを実行すると、「型アサーションが正しく動作しています。」というメッセージが表示されるはずです。

なぜなら、valueに格納されている文字列と比較している文字列は同じだからです。

注意点として、型アサーションはあくまでコンパイル時のみの動作であり、実行時に何らかの変換や動作を加えるわけではありません。

また、不適切な型アサーションを行うと、予期しないエラーが発生する可能性があるため注意が必要です。

応用例として、型アサーションを使ってオブジェクトのプロパティを取得する場面が考えられます。

下記のサンプルコードでは、オブジェクトobjany型として宣言されているため、そのプロパティの型も不明確です。

そこで、型アサーションを使用して、プロパティnamestring型であることを宣言しています。

let obj: any = {
    name: "Tanaka",
    age: 30
};

let assertedName: string = <string>obj.name;

if (assertedName === "Tanaka") {
    console.log("オブジェクトのプロパティの型アサーションも正しく動作しています。");
}

このコードでは、「オブジェクトのプロパティの型アサーションも正しく動作しています。」というメッセージが表示されるでしょう。

●注意点と対処法

TypeScriptで比較演算子を使う上での注意点とそれに対する対処法を解説します。

比較演算子はシンプルに見えますが、予期せぬ挙動が発生する場面があるので、その点を抑えておきましょう。

○型の違いによる比較の落とし穴

このコードでは異なる型の変数を比較する際の注意点を表しています。

この例では数値と文字列を比較してみます。

let num: number = 10;
let str: string = "10";

if (num == str) {
    console.log("numとstrは等しい");
} else {
    console.log("numとstrは等しくない");
}

このコードを実行すると、「numとstrは等しい」と表示されます。

これは、== 演算子は型変換を行った上での比較をするためです。

しかし、TypeScriptで安全なコードを書く上で、このような型変換を伴う比較は避けるべきです。

対策としては、型変換を伴わない === 演算子を使用することです。

この場合、数値と文字列は等しくないと判断されます。

if (num === str) {
    console.log("numとstrは等しい");
} else {
    console.log("numとstrは等しくない");
}

このコードでは、「numとstrは等しくない」と表示されます。

○厳密等価と抽象等価の違い

TypeScriptの比較において、=====の違いは非常に重要です。

このコードではこの2つの違いを示す例を紹介しています。

この例ではnullとundefinedを比較してみます。

let val1: null = null;
let val2: undefined = undefined;

if (val1 == val2) {
    console.log("val1とval2は等しい");
} else {
    console.log("val1とval2は等しくない");
}

if (val1 === val2) {
    console.log("val1とval2は厳密に等しい");
} else {
    console.log("val1とval2は厳密に等しくない");
}

上記のコードを実行すると、”val1とval2は等しい” と “val1とval2は厳密に等しくない” という結果が出力されます。

これは、==はnullとundefinedを等価と見なす一方、===は型まで厳密に比較するための結果です。

このような予期せぬ型変換を避けるために、TypeScriptでは===を使用することを推奨します。

●比較演算子のカスタマイズ方法

比較演算子は日常のプログラミングで頻繁に使用されるものですが、場面や要件に応じてカスタマイズする必要が出てくることもあります。

特にTypeScriptを使用している場合、型の安全性を高めつつ、柔軟な比較関数の実装が求められることが多いです。

ここでは、独自の比較関数の作成とその利用方法を中心に、TypeScriptでの比較演算子のカスタマイズ方法を詳しく解説していきます。

○独自の比較関数の作成と利用

まずは、基本的なカスタム比較関数の作成方法から始めてみましょう。

このコードでは、二つの数値を引数として受け取り、その差が特定の範囲内にあるかどうかを判定する独自の比較関数を紹介しています。

この例では、数値aと数値bの差が10以内であるかどうかを判定しています。

function isWithinRange(a: number, b: number, range: number = 10): boolean {
  return Math.abs(a - b) <= range;
}

// 使用例
const result1 = isWithinRange(100, 105); // true
const result2 = isWithinRange(100, 112); // false
const result3 = isWithinRange(100, 95, 5); // true

上記のコードを実行すると、result1の結果はtrueとなり、result2の結果はfalseとなります。

result3では、第3引数に5を指定しているため、範囲を5として比較が行われ、結果はtrueとなります。

このようなカスタム比較関数を作成することで、プロジェクトや要件に合わせた柔軟な比較が可能になります。

特にTypeScriptを使用する場合、関数の引数や戻り値に型を指定することで、型の安全性を確保しつつ効率的な比較が行えます。

独自の比較関数は、様々なシチュエーションでの応用が考えられます。

例えば、オブジェクトの特定のプロパティ同士の比較、配列内の要素の比較、文字列の部分的な比較など、用途に応じて関数をカスタマイズすることができます。

最後に、独自の比較関数を活用することで、プログラムの可読性や保守性も向上します。

既存の比較演算子だけでは表現しきれない複雑な比較ロジックも、関数化することで簡潔かつ明瞭に表現することができるのです。

まとめ

TypeScriptでの比較演算子を学ぶ過程は、プログラミング初心者や中級者にとって非常に役立つステップとなるでしょう。

今回の記事では、基本的な比較演算子の使い方から、より高度な比較方法、さらにはカスタマイズの方法まで、詳細にわたって解説してきました。

この記事を通じて、TypeScriptの比較演算子に関する知識を深め、より質の高いコードを書くための一助となったことを願っています。

今後もプログラミングに関する様々なテーマでの深い学びを追求していきましょう。