Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript type issue in map function of mixed types react

I have defined two types, Team and Position. They are both part of an array that I iterate over in my react component.

based on the types defined below in my map function I am seeing the following error.

Examples of errors I am seeing.

Property 'name' does not exist on type 'Position'. [2339]

Property 'position' does not exist on type 'Team'. [2339]

Is it not possible to check that the array contains either type?

My code looks like as follows:

type Team = {
   name: string; 
   city: string;
} 

type Position = {
   position: number;
}

const Component = () => {
    const teamsAndPosition = [
       {
        name: 'Arsenal', 
        city: 'London',
       },
      {
        name: 'Everton', 
        city: 'Liverpool',
       },
      { 
         position: 2
      }
    ];

    const [list, setList] = useState<Array<Team | Position >>(teams)
    
    list.map((item: Team | Position) => {
       return item.name ? (
         <div>
           // I am seeing an error for these below
           <p>{item.name}</p>
           <p>{item.city}</p>
         </div>
       ) : (
         <p>{item.position}</p>
       )
    })
}    
like image 744
peter flanagan Avatar asked Aug 08 '26 20:08

peter flanagan


1 Answers

When dealing with a variable that might be one of two (or more) types you can check that a unique property on the object exists before dealing with the object so typescript can deduce what type it is.

Example:

interface IObjectYo {
  someProp: number
  same: boolean
}

interface IDifObjYo {
  otherProp: number
  same: boolean
}

function example(someArg: IObjectYo | IDifObjYo) {
  console.log(someArg.someProp) // tsc complains because someProp doesn't belong to IDifObjYo
  if ('someProp' in someArg) {
    console.log(someArg.someProp) // tsc knows it must be type IObjectYo because someProp only belongs to IObjectYo
  } else {
    console.log(someArg.otherProp) // tsc knows this is IDifObjYo because the first condition failed (which means it must be of type IDifObjYo)
  }
  if ('same' in someArg) {
    console.log(someArg.someProp) // make sure the property is indeed unique between the possible types or tsc can't infer
  }
}

In your case (and I'm not a React guy) you could do something like this:

type Team = {
   name: string;
   city: string
} 

type Position = {
   position: number;
}

const Component = () => {
    const [list, setList] = useState<Array<Team | Position >>(teams)

    list.map((item: Team | Position) => {
       return 'name' in item ? (
          <div>
             <p>{item.name}</p>
             <p>{item.city}</p>
          </div>
       ) : (
        <p>{item.position}</p>
       )
    })
}    
like image 101
Cory Kleiser Avatar answered Aug 10 '26 10:08

Cory Kleiser