ユニオンタイプを使ったpropsの定義

ユニオン型(|)を使うと、複数のpropsパターンのうちいずれかを許容できます。異なる型構造を1つのコンポーネントで柔軟に扱いたい場合に便利です。


🎯 例:状態に応じてpropsの型を分岐させる

type LoadingState = {
  isLoading: true;
};

type LoadedState = {
  isLoading: false;
  data: string;
};

type Props = LoadingState | LoadedState;

const DataBlock = (props: Props) => {
  if (props.isLoading) {
    return 
<p>読み込み中...</p>;
  }

  // propsはこの時点でLoadedStateとして推論される
  return 
<p>データ: {props.data}</p>;
};

✅ ユニオン型を使うと、条件分岐と組み合わせて型を絞り込む(型ガード)ことが可能です。


🎯 例:表示形式のバリエーションを切り替える

type TextProps = {
  type: "text";
  content: string;
};

type ImageProps = {
  type: "image";
  src: string;
  alt: string;
};

type Props = TextProps | ImageProps;

const Display = (props: Props) => {
  switch (props.type) {
    case "text":
      return 
<p>{props.content}</p>;
    case "image":
      return <img src={props.src} alt={props.alt} />;
  }
};

🧠 typeなどの判別可能なプロパティ(discriminated union)を使うことで、TypeScriptが自動で型を推論してくれます。



ベースPropsを継承し、ユニオン部分だけを切り替える

ユニオンタイプをより明確・安全に管理する方法として、共通部分をベース型に定義し、変化する部分だけを派生型で表現するという手法があります。


🎯 例:共通レイアウトを持つ複数タイプの表示コンポーネント

✅ ベース型を定義

type BaseProps = {
  title: string;
};

✅ 派生型ごとにユニオン部分を分離

type TextProps = BaseProps & {
  type: "text";
  content: string;
};

type ImageProps = BaseProps & {
  type: "image";
  src: string;
  alt: string;
};

type Props = TextProps | ImageProps;

✅ コンポーネントで使う

const MediaBlock = (props: Props) => {
  return (
    <div className="media">

<h2>{props.title}</h2>
      {props.type === "text" ? (

<p>{props.content}</p>
      ) : (
        <img src={props.src} alt={props.alt} />
      )}
    </div>
  );
};

✅ なぜこの設計が良いのか?

  • 🔁 共通プロパティ(titleなど)を毎回繰り返す必要がない
  • 🧠 型の拡張がしやすく、保守・再利用にも強い
  • 🛡️ 判別可能ユニオンによる型安全な条件分岐が可能

🎯 さらに複雑なバリエーションにも応用可能

type BaseProps = {
  id: string;
  onSelect: (id: string) => void;
};

type VideoProps = BaseProps & {
  type: "video";
  url: string;
};

type AudioProps = BaseProps & {
  type: "audio";
  file: string;
};

type MediaProps = VideoProps | AudioProps;

このように、共通のインターフェース(ベース型)を継承しつつ、typeで分岐できる構造は、UIの構成や状態管理など幅広い場面で役立ちます。

コメントを残す 0

Your email address will not be published. Required fields are marked *