Home > Back-end >  Typescript: error finding field in union type
Typescript: error finding field in union type

Time:11-14

I'm using a prop bodyData that receives 2 differently typed arrays depending on which page I am on.

What am I doing wrong here? It seems like the 2 arrays are interconnected/conflicting. Thanks.

The 2 different array interfaces

Listings interface

export interface ListingsItems{
  id: number;
  img: string;
  itemNo: number;
  source: string;
  title: JSX.Element;
  sell: number;
  cost: number;
  profile: number;
  markup: JSX.Element;
  stock: JSX.Element;
  created: JSX.Element;
}


export const listingsData: ListingsItems[] = [
  {
    id: 1,
    img: dataoneimg,
    itemNo: 1234546789,
    source: 'Amazon',
    title: (
      <div className="w-title align-items-center my-auto">
        {' '}
        <p className="mb-0">Title of the product</p>{' '}
      </div>
    ),
    sell: 30.4,
    cost: 34.44,
    profile: 309,
    markup: <div className="pl-2">30%</div>,
    stock: (
      <div className="pl-1">
        <i className="d-green far fa-check-circle"></i> 2
      </div>
    ),
    created: (
      <div className="d-flex justify-content-between">
        13/07/2021 12:56
        <img className="ml-4" src={editicon} />
        <img className="ml-3" src={doticon} />
      </div>
    )
  },
]

Order types

export interface OrderItems{
  id: number;
  img: string;
  sale: string;
  qty: string;
  source: string;
  title: string;
  sold: string;
  cost: string;
  fees: string;
  profit: string;
  margin: string;
  orderOn: string;
  state: string
}

export const orderData: OrderItems[] = [
  {
    id: 1,
    img: dataoneimg,
    sale: '-',
    source: 'Amazon',
    title: 'Title of the product',
    qty: '1',
    sold: '€15.99',
    cost: '€12.99',
    fees: '€1.00',
    profit: '€1.00',
    margin: '-',
    orderOn: '13/07/12:56',
    state: 'Error'
  },
]

How I'm using them to define my bodyData prop

interface props {
  bodyData: Array<ListingsItems | OrderItems>;
}

How I'm using the bodyData prop in a component

<ListingsTable bodyData={listingsData} headerData {listingsHeadingData} />

The error that I'm getting when I try to map over the bodyData

/home/moshe/upwork-gigs/hgrweb/src/components/tables/ContentTable.tsx
TypeScript error in /home/moshe/upwork-gigs/hgrweb/src/components/tables/ContentTable.tsx(72,66):
Property 'sale' does not exist on type 'ListingsItems | OrderItems'.
  Property 'sale' does not exist on type 'ListingsItems'.  TS2339

    70 |                   <img src={obj.img} alt="" />
    71 |                 </td>
  > 72 |                 <td className="obj-sale-body order-td-none">{obj.sale ? obj.sale : obj.itemNo}</td>
       |                                                                  ^
    73 |                 <td className="obj-sale-body order-td-none">{obj.source}</td>
    74 |                 <td className="obj-sale-title order-td-none">{obj.title}</td>
    75 |                 <td className="obj-sale-qty order-td-none">{obj.qty ? obj.qty : obj.sell}</td>

CodePudding user response:

It might make your code if you also define a type guard:

const isOrderItems(item: ListingsItems|OrderItems): item is OrderItems => !!item.sale; 

Then you can use that to have TS disambiguate the type in each branch:

 <td className="obj-sale-body order-td-none">{isOrderItems(obj) ? obj.sale : obj.itemNo}</td>

CodePudding user response:

Your ListingsItems doesn't have a field sale. OrderItems does.

The error message pretty much says it all.

If you look at this repl, you can see the errors that happen when you try to dereference the sale property on the wrong type.

  • Related