0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オプションプロパティを使用する際の注意点

Posted at

気軽に使えるオプションプロパティ

以下のような既存の型に新しいプロパティを追加したいとします。

type User = {
	id: number
	name: string;
	// avatorUrl 追加したい
}

この時に? を使用してプロパティをオプショナルに指定できます。こうすることで、avatorUrlがいらない既存の関数やコンポーネントなどの既存のコードに影響を与えずにプロパティを追加することができます。

type User = {
	id: number;
	name: string:
	avatorUrl?: string
}

オプションプロパティのデメリット

値の渡し忘れ

例えばavatorUrlが実際にはUI表示に必須だった場合でも、オプショナルにしてしまうとTypeScriptの型チェックが働かないため意図しない挙動となってしまいます。

組み合わせ爆発

オプショナルプロパティが複数存在する場合、その組み合わせは指数的に増加します。
例:オプショナルが10個 → 2¹⁰ = 1024通り
すべての組み合わせを網羅するのは辛いですね

型同士の相互作用

たとえば、「プロパティ A がある場合は B も必要」といった相関関係などにあるものが多いと思います。このように1つの型の中で複数の状態は可読性が低く、バグを起こしやすいコードの原因になってしまいます。

解決策

判別可能ユニオンを使用してモデリングする

上の型同士の相互作用の項目に関連しますが、TypeScriptのメリットを享受するために有効な状態のみ表現する型をつくりましょう。これにより状態が明確になり、コードが読みやすくバグを未然に防ぐ設計となります。

以下のような型だと全てのプロパティの状態を考慮しなくてはならず、バグが入りやすくなります。例えばisLoading がtureでdataが存在する場合、何を表示すれば良いんでしょうか...

type LoadState = {
  isLoading: boolean;
  data?: string;
  error?: string;
};

以下のコードは判別可能ユニオンを使用して、それぞれの状態をモデリングしています。状態が明確なので、コードは書きやすくなり余計なことを考えなくて済みます。

type LoadState =
  | { status: 'loading' }
  | { status: 'success'; data: string }
  | { status: 'error'; errorMessage: string };

const Content = (state: LoadState) => {
  switch (state.status) {
    case 'loading':
      return <p>読み込み中</p>;
    case 'success':
      return <p>{state.data}</p>;
    case 'error':
      return <p>{state.errorMessage}</p>;
  }
};

オプションプロパティを使う場面

とはいえオプションプロパティを使用べき場面、使わざるを得ない場面も当然あります。

  • APIの型を表す場合
  • 巨大な設定項目
  • オプションなプロパティ(例:ミドルネームなど)

まとめ

  • オプションプロパティのデメリットを理解しておく
  • オプションプロパティを追加する前に必須にできないかを考える

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?