Optional chaining (?.) と Nullish coalescing operator (??) の比較

2024-04-02

TypeScriptにおけるセーフナビゲーション演算子(?.)とnullプロパティパス

セーフナビゲーション演算子は、プロパティが存在しない場合でもエラーが発生せずにnullまたはundefinedを返す演算子です。

const obj = {
  name: "John",
  age: 30,
};

const name = obj?.name; // "John"
const age = obj?.address?.city; // undefined

// エラーが発生しない
console.log(name); // "John"
console.log(age); // undefined

nullプロパティパスは、プロパティチェーン内のnullまたはundefinedを無視して、存在するプロパティにアクセスするための構文です。

const obj = {
  name: "John",
  address: {
    city: "New York",
  },
};

const city = obj?.address?.city; // "New York"

// 従来の書き方
const city2 = obj.address && obj.address.city; // "New York"

// nullプロパティパスの方が簡潔で読みやすい
console.log(city); // "New York"
console.log(city2); // "New York"

セーフナビゲーション演算子とnullプロパティパスの使い分け

セーフナビゲーション演算子は、単一のプロパティにアクセスする場合に便利です。一方、nullプロパティパスは、プロパティチェーン内の複数のプロパティにアクセスする場合に便利です。

const obj = {
  name: "John",
  address: {
    city: "New York",
  },
};

// セーフナビゲーション演算子
const name = obj?.name; // "John"

// nullプロパティパス
const city = obj?.address?.city; // "New York"

// 複数のプロパティにアクセスする場合
const fullName = obj?.name?.toUpperCase(); // "JOHN"
const address = obj?.address?.city?.toUpperCase(); // "NEW YORK"

セーフナビゲーション演算子とnullプロパティパスは、TypeScriptでnullまたはundefinedの可能性のあるプロパティに安全にアクセスするための便利なツールです。これらのツールを使いこなすことで、コードをより簡潔で読みやすくすることができます。




// オブジェクト
const person = {
  name: "John",
  age: 30,
  address: {
    city: "New York",
    state: "NY",
  },
};

// セーフナビゲーション演算子
const name = person?.name; // "John"
const age = person?.age; // 30
const city = person?.address?.city; // "New York"
const state = person?.address?.state; // "NY"

// nullプロパティパス
const fullName = person?.name?.toUpperCase(); // "JOHN"
const address = person?.address?.city?.toUpperCase(); // "NEW YORK"

// 存在しないプロパティへのアクセス
const nonExistingProperty = person?.nonExistingProperty; // undefined

// nullまたはundefinedの場合のデフォルト値
const defaultName = person?.name ?? "Unknown"; // "John"
const defaultAge = person?.age ?? 0; // 30
const defaultCity = person?.address?.city ?? "Unknown City"; // "New York"

// オプションの引数
function greet(person: { name?: string }): string {
  return person?.name ?? "Hello, stranger!";
}

const greeting = greet(person); // "Hello, John!"

// ネストされたオブジェクト
const nestedObject = {
  data: {
    value: 10,
  },
};

const value = nestedObject?.data?.value; // 10

// 配列
const numbers = [1, 2, 3, 4, 5];

const firstNumber = numbers?.[0]; // 1
const lastNumber = numbers?.[numbers.length - 1]; // 5

// 存在しない要素へのアクセス
const nonExistingElement = numbers?.[100]; // undefined

// nullまたはundefinedの場合のデフォルト値
const defaultValue = numbers?.[0] ?? 0; // 1

// オプションの要素
function sum(numbers: number[]): number {
  return numbers?.[0] ?? 0 + numbers?.[1] ?? 0;
}

const sumOfFirstTwoNumbers = sum([1, 2]); // 3

// マップ
const map = new Map([
  ["key1", "value1"],
  ["key2", "value2"],
]);

const value1 = map?.get("key1"); // "value1"
const value2 = map?.get("key2"); // "value2"

// 存在しないキーへのアクセス
const nonExistingKey = map?.get("nonExistingKey"); // undefined

// nullまたはundefinedの場合のデフォルト値
const defaultValue2 = map?.get("key1") ?? "default value"; // "value1"

// オプションのキー
function getValue(map: Map<string, string>, key: string): string {
  return map?.get(key) ?? "default value";
}

const valueFromMap = getValue(map, "key1"); // "value1"

// Set
const set = new Set([1, 2, 3, 4, 5]);

const hasValue1 = set?.has(1); // true
const hasValue2 = set?.has(2); // true

// 存在しない値へのアクセス
const nonExistingValue = set?.has(100); // false

// オプションの値
function hasValue(set: Set<number>, value: number): boolean {
  return set?.has(value) ?? false;
}

const hasValueInSet = hasValue(set, 1); // true



TypeScriptでnullまたはundefinedの可能性のあるプロパティにアクセスする他の方法

従来のnullチェック

const obj = {
  name: "John",
  age: 30,
};

const name = obj.name;
if (name === null || name === undefined) {
  // nameはnullまたはundefined
} else {
  // nameはnullまたはundefinedではない
}

const age = obj.age;
if (age === null || age === undefined) {
  // ageはnullまたはundefined
} else {
  // ageはnullまたはundefinedではない
}

Optional chainingは、JavaScriptの提案機能であり、TypeScript 4.0以降で使用できます。

const obj = {
  name: "John",
  age: 30,
};

const name = obj?.name; // "John"
const age = obj?.age; // 30

// 存在しないプロパティへのアクセス
const nonExistingProperty = obj?.nonExistingProperty; // undefined

// nullまたはundefinedの場合のデフォルト値
const defaultName = obj?.name ?? "Unknown"; // "John"
const defaultAge = obj?.age ?? 0; // 30
const obj = {
  name: "John",
  age: 30,
};

const name = obj.name ?? "Unknown"; // "John"
const age = obj.age ?? 0; // 30

// 存在しないプロパティへのアクセス
const nonExistingProperty = obj.nonExistingProperty ?? "Unknown"; // "Unknown"

エラーハンドリング

const obj = {
  name: "John",
  age: 30,
};

try {
  const name = obj.name;
  const age = obj.age;

  // nameとageを使用する
} catch (error) {
  // エラー処理
}

型ガード

const obj: { name?: string; age?: number } = {
  name: "John",
};

if (obj.name !== null && obj.name !== undefined) {
  const name = obj.name;

  // nameを使用する
}

if (obj.age !== null && obj.age !== undefined) {
  const age = obj.age;

  // ageを使用する
}

これらの方法にはそれぞれメリットとデメリットがあります。状況に応じて適切な方法を選択する必要があります。


typescript


インターフェース、型パラメーター、型ガードも活用!TypeScriptで基底クラスのメンバーにアクセスする

基底クラスのメンバーには、以下の2種類があります。プロパティ: データを表す変数のようなものです。メソッド: 処理を実行する関数のようなものです。基底クラスのメンバーにアクセスする場所は、以下の2つが考えられます。派生クラス: 基底クラスを継承したクラスです。...


TypeScript でオブジェクトがインターフェースを実装しているかどうかをランタイムで確認する方法

TypeScript では、インターフェースを使用してオブジェクトの構造を定義できます。インターフェースは、オブジェクトが持つべきプロパティとメソッドを定義しますが、実装は規定しません。オブジェクトがインターフェースを実装しているかどうかをランタイムで確認するには、いくつかの方法があります。...


Firebase Hosting を使って Angular アプリをデプロイする方法

Firebase Hosting は、Angular アプリを簡単にデプロイできるサービスです。 Firebase プロジェクトを作成し、Angular アプリをビルドして dist フォルダに配置します。 その後、Firebase CLI を使用してアプリをデプロイできます。...


「keyof typeof」を使いこなして、TypeScriptの型システムをマスターしよう

基本的な仕組み「keyof」:オブジェクトのプロパティ名を取得「typeof」:変数や型の型情報を取得**「keyof typeof」**は、これらの2つの演算子を組み合わせることで、オブジェクトの型情報からプロパティ名のみを取り出すことができます。...


React TypeScript useRef エラー「not assignable to type LegacyRef」の分かりやすい解決策

このエラーが発生する原因このエラーは、Reactの useRef フックと TypeScript の型システムの間で型不一致が発生していることを示しています。 useRef フックは、DOM要素への参照を保持するために使用されますが、TypeScriptではその型を厳密にチェックする必要があります。...


SQL SQL SQL SQL Amazon で見る



【徹底解説】ネストした JavaScript オブジェクトのキーの有無を確認する方法

in 演算子は、オブジェクト内に特定のプロパティが存在するかどうかを確認するために使用されます。構文は以下の通りです。この式は、propertyName が object のプロパティであるかどうかを true または false で返します。


TypeScript ?. 演算子:null または undefined の可能性がある値に安全にアクセスする方法

?. 演算子は、オプションチェーン演算子と呼ばれる演算子で、null または undefined の可能性がある値に対して安全にアクセスするための便利な機能です。?. 演算子は、プロパティやメソッドのチェーン呼び出しにおいて、null または undefined の可能性がある中間オブジェクトを安全に処理するために使用されます。