zukucode
主にWEB関連の情報を技術メモとして発信しています。

TypeScript オプショナルチェーンとNull合体演算子の使い方

APIから受け取るデータには、値が存在しない項目が含まれることがあります。

TypeScriptでは、オプショナルチェーンの?.とNull合体演算子の??を使用すると、nullやundefinedを安全に扱えます。

これらは、欠けてもよい値を簡潔に扱うための演算子です。本来必須の値が欠けている問題を隠すために使うものではありません。また、空文字や0を有効な値として残したい場合は、すべてのfalsy値を置き換える||ではなく??を選びます。

値がない可能性を型で表す

以下は、利用者と住所を表す型です。

type Address = {
  city: string;
  postalCode?: string;
};

type User = {
  name: string;
  address?: Address;
};

プロパティ名の後ろに?を付けると、そのプロパティが存在しない可能性を表せます。

user.address.cityと直接書くと、addressがundefinedかもしれないためTypeScriptでエラーになります。

オプショナルチェーンで参照する

const city = user.address?.city;

addressが存在すればcityを返し、存在しなければundefinedを返します。

複数の階層へ続けて使用することもできます。

const length = user.address?.postalCode?.length;

この場合、addressまたはpostalCodeが存在しなければlengthはundefinedです。

Null合体演算子で初期値を設定する

undefinedの代わりに表示用の文字列を使用したい場合は、??を組み合わせます。

const city = user.address?.city ?? '未設定';
const postalCode = user.address?.postalCode ?? '郵便番号なし';

左側がnullまたはundefinedの場合だけ、右側の値を使用します。

||との違い

||は、空文字、数値の0、falseも値がないものとして扱います。

const count = 0;

console.log(count || 10); // 10
console.log(count ?? 10); // 0

件数の0や設定値のfalseを有効な値として扱いたい場合は、??を使用します。

type Settings = {
  pageSize?: number;
  showHelp?: boolean;
};

const pageSize = settings.pageSize ?? 20;
const showHelp = settings.showHelp ?? true;

pageSizeが0なら0、showHelpがfalseならfalseをそのまま使用します。

配列の要素を安全に取得する

配列の検索結果にも使用できます。

type Product = {
  productId: string;
  name: string;
};

const products: Product[] = [
  { productId: 'p1', name: 'ノート' },
];

const productName = products.find((item) => item.productId === 'p2')?.name
  ?? '商品が見つかりません';

findは対象が見つからない場合にundefinedを返します。

?.nameで安全に名前を取得し、見つからなければ??の右側を使用します。

関数を安全に呼び出す

関数自体が存在しない可能性がある場合にも?.を使用できます。

type Props = {
  onComplete?: () => void;
};

const save = (props: Props) => {
  // 保存処理
  props.onComplete?.();
};

onCompleteが渡されている場合だけ関数を実行します。

値を代入する用途には使えない

オプショナルチェーンは値の参照に使用します。左辺へ値を代入することはできません。

エラーになる例
user.address?.city = '東京';

値を変更する場合は、先に存在を確認します。

if (user.address) {
  user.address.city = '東京';
}

?.を追加するとエラーは消せますが、本来必須のデータが欠けている問題を見逃す場合があります。

値がなくてもよい項目だけをoptionalにし、必須項目がない場合は入力チェックやAPIレスポンスの検証でエラーにします。

?.は途中の値がない場合にundefinedを返し、??はnullまたはundefinedの場合の初期値を指定します。この2つを使い分けることで、値がない場合の処理を簡潔に書けます。


関連記事