cfoster5
cfoster5

Reputation: 1826

Property does not exist on type 'object' - Union type

I have defined two interfaces:

interface movieProps {
  adult: boolean,
  backdrop_path: string,
  genre_ids: number[],
  id: number,
  original_language: string,
  original_title: string,
  overview: string,
  popularity: number,
  poster_path: string,
  release_date: string,
  title: string,
  video: boolean,
  vote_average: number,
  vote_count: number,
  mediaType: string,
  documentID: string
}

interface gameReleaseDate {
  id: number,
  category: number,
  created_at: number,
  date: number,
  game: game,
  human: string,
  m: number,
  platform: number,
  region: number,
  updated_at: number,
  y: number,
  documentID: string,
  mediaType: string
}

I have defined a variable with a union type using allCountdownItems: movieProps[] | gameReleaseDate[] that contain both types of objects.

I am using .map() to render info for each item. I am doing this by using:

return (
  <div>
    {(this.state.allCountdownItems as Array<movieProps | gameReleaseDate>).map(item => {
      return (
        <h2>{item.mediaType === "movie" ? item.title : item.game.name}</h2>
      )
    })}
  </div>
)

This give me the following error:

Property 'title' does not exist on type 'movieProps | gameReleaseDate'. Property 'title' does not exist on type 'gameReleaseDate'.ts(2339)

How can I solve this without declaring item as an any type?

Upvotes: 1

Views: 103

Answers (1)

basarat
basarat

Reputation: 275799

You are trying to discriminate between the union with item.mediaType === "movie"

In order for that to work you need to declare literal members on the union member i.e.

interface movieProps {
  adult: boolean,
  backdrop_path: string,
  genre_ids: number[],
  id: number,
  original_language: string,
  original_title: string,
  overview: string,
  popularity: number,
  poster_path: string,
  release_date: string,
  title: string,
  video: boolean,
  vote_average: number,
  vote_count: number,
  mediaType:'movie' // HERE
  documentID: string
}

interface gameReleaseDate {
  id: number,
  category: number,
  created_at: number,
  date: number,
  game: game,
  human: string,
  m: number,
  platform: number,
  region: number,
  updated_at: number,
  y: number,
  documentID: string,
  mediaType:'game' // HERE
}

More

Discriminated unions TypeScript

Upvotes: 1

Related Questions