2

Been battling with this problem for a while now so I turned to Google and now to you since I didn't find anything.

Small background to my problem: I want to render a table that renders conditional rows based on what type each row is.

This is what I got so far:

interface TableRowProps {
  disabled?: boolean
}

type AnimalProps = {
  type: 'animal'
  data?: AnimalData
}

type PersonProps = {
  type: 'person'
  data?: PersonData
}

type ConditionalProps = AnimalProps | PersonProps

const TableRow: FC<TableRowProps & ConditionalProps> = ({ type, data, disabled }) => {
...

Naturally I would use this TableRow component in a table to render each row individually. Depending on what state the app is I would choose what type the row would be and also pass the data through iterating through an array

In my code I would use the "type" property to determine what the "data" property holds to render the row accordingly

if (type === 'animal') {
  return (
    <tr>
      <td>{data.animalProp}</td>
    </tr>
  )
}
    
if (type === 'person') {
  return (
    <tr>
      <td>{data.personProp}</td>
    </tr>
  )
}

This is all fine and dandy in VS Code. TypeScript is not complaining with any squiggly red lines or anything like that but at build time in the browser I get:

Property 'animalProp' does not exist on type 'PersonType | AnimalType'.
  Property 'animalProp' does not exist on type 'PersonType'.

The workaround would be to use "as" to set the types on each occurrence but there has to be a cleaner way out there.

Any help that points me in the right direction would be much appreciated.

Thanks a bunch in advance!

Best regards, //G

1 Answer 1

1

I think that in your case, type guards could be helpful:

type Person = {
  type: 'person'
}

type Animal = {
  type: 'animal'
}

function isPerson(entity: Person | Animal): entity is Person {
  return (entity as Person).type === 'person';
}
  
const entity: Person | Animal = { type: 'person' }

if (isPerson(entity)) {
  console.log('person')
} else {
  console.log('animal')
}

In this case, person would get logged in the console. Also note that the proper type would be inferred inside the if / else brackets. You can have the detailed explanation in the docs.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey @Mentlegen, thanks for your reply! Yes, this seems to be doing the trick and by the book as well, but I was maybe hoping there would be a slightly cleaner solution. I'm just wondering why TS can't catch my error before build time. Any idea?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.