🚥

オブジェクトAに含まれるオブジェクトBの配列とオブジェクトCの配列が混合で入る配列の取り回し(オブジェクトの共用体型)

2023/02/01に公開

タイトル分かりづらくてすみません。
前回と同じく、業務中に学んだ内容についてのメモになります。

やりたかったこと

↓ のような型定義があったとする。

type Fuga = {
  id: string
  name: string
  ...
}

type Piyo = {
  id: string
  name: string
  ...
}

type Hoge = {
  id: string
  name: string
  fugas: Fuga[]
  piyos: Piyo[]
}

Hoge.fugasHoge.piyos を配列 metaSyntaxVariables に入れた後で、中の要素が FugaPiyo かを判別したい。

詰まったポイント

FugaPiyo それぞれ固有のプロパティで判別しようかと思ったけど、今後何らかのタイミングでそのプロパティが変更された時に動かなくなる可能性がある。。

解決したやり方

type, value のプロパティが共通しているオブジェクトの交差型 (ここでは Item)を用意する。

type FugaItem = {
  type: 'fuga'
  value: Fuga
}
type PiyoItem = {
  type: 'piyo'
  value: Piyo
}

type Item = FugaItem | PiyoItem

Item 型の配列を生成する。

const metaSyntaxVariables: Item[] = [
  ...hoge.fugas.map(
    (fuga): FugaItem => ({
      value: { ...fuga },
      type: 'fuga'
    })
  ),
  ...hoge.piyos.map(
    (piyo): PiyoItem => ({
      value: { ...piyo },
      type: 'piyo'
    })
  )
]

作った配列を .map() などで回すと、要素が type の中身によって Fuga 型と Piyo 型に振り分けられるようになる。

metaSyntaxVariables.map(
  (item) => {
    switch (item.type) {
      case 'fuga': {
        ... // <- このコードブロックでは item が Fuga 型として推論される
      }
      case 'piyo': {
        ... // <- このコードブロックでは item が Piyo 型として推論される
      }
    }
  }
)

Discussion