Undefined と Null

それぞれundefinednull型が用意されてます。

const foo: undefined = undefined;
const bar: null = null;

もし、string | undefinedのようなUnionの場合、if構文などで絞り込むことができます。

const foo: string | undefined = '';

if (foo !== void 0) {
    foo; // const foo: string;
}

Optional Chaining

TypeScriipt@^3.7 からundefinedかもしれないオブジェクトのプロパティへのアクセスを簡易に記述できるようになりました。

それ以前までは以下のような型の時、

interface MyObject {
  foo?: {
    bar?: {
      baz(): void;
    };
  };
}

プロパティbazへ安全にアクセスしたいなら以下のようにする必要がありました。

const obj: MyObject = {} as MyObject;

if (
  obj.foo !== void 0 &&
  obj.foo.bar !== void 0
) {
  obj.foo.bar.baz();
}

@^3.7 からは以下のように書くことができます。

obj.foo?.bar?.baz();

?.という書き方でプロパティにアクセスすることで、値が対象のプロパティがundefinednullの場合はundefinedを返し、そうでない場合は対象のプロパティ値を返すようになります。つまり、途中にundefinednullがあればundefined、そうでなければ期待した結果が返ります。

Nullish Coalescing

TypeScriipt@^3.7 から対象の値がundefinednullの時用のフォールバック値を設定する為の構文が追加されました。これはundeefinedかnullかもしれない値 ?? フォールバック値のように??を間に記述します。undefinednullでない場合はそのままその値が使われます。

例えば以下のfnは渡したプリミティブ値をそのまま返してくれるものです。

const fn = <
  Str extends string,
  Num extends number
>(obj: {
  str?: Str;
  num?: Num;
}) => {
  const str = obj.str ?? ('str' as const);
  const num = obj.num ?? (123 as const);

  return { str, num };
};

const result = fn({
  str: '' as const,
  num: 0 as const
});
// const result: {
//   str: "" | "str";
//   num: 0 | 123;
// }

console.log(result);
// {str: "", num: 0}

古くからある||を使うと''0はfalsy(falseとして扱われる)値なので{str: "str", num: 123}という値が返るようになるという違いがあります。

組み合わせる

Optional Chaining は値が空の時必ずundefinedを返すため、空の時のフォールバック値を設定できる Nullish Coalescing との相性が良いです。

これは深いネストを持つオブジェクトにデフォルト値を設定するのに便利です。

type Obj = { foo?: { bar?: { baz: string } } };

const expectToReturnDefault: Obj = {};
console.log(
  expectToReturnDefault.foo?.bar?.baz ?? "default"
);
// 'default'

const expectToReturnBazValue: Obj = {
  foo: { bar: { baz: "baz" } }
};
console.log(
  expectToReturnBazValue.foo?.bar?.baz ?? "default"
);
// 'baz'