Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript unable to understand conditional render pathway

I have the following code:

import * as React from 'react'

type ComponentConfig = [true, {name: string}] | [false, null]

const useComponent = (check: boolean): ComponentConfig => {
  if (check) {
    return [true, {name: 'Some Name'}]
  }
  return [false, null]
}

const Component = (props: {name: string}) => {
  return <div>Hello {props.name}</div>
}

const Parent = () => {
  const [shouldRender, props] = useComponent(true);

  return (
    <>
      <div>Some Heading</div>
      {shouldRender && <Component {...props} />}
    </>
  )
}

As you can see, there is a Parent and Child component, however it should be rendered conditionally based on some logic, here represented as "check" argument.
The utility method returns tuple of boolean and props. More specifically, it returns set of props for true case but returns null for false case.
My initial expectation was that Typescript would be able to understand these pathways.

But I get the following error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Type '{ name?: string | undefined; }' is not assignable to type '{ name: string; }'.
  Types of property 'name' are incompatible.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.

How can I resolve this error? The above snippet is also reproducible in this Playground Link

>Solution :

Until Typescript 4.6 (yet to be released at the time of writing) the compiler can’t understand that shouldRender and props are related in any way.

If you wait for 4.6, your code should work AS IS. And you can see this in the TS playground if you use the nightly version: Playground Link

Until 4.6 you can use the tuple directly, without destructuring, TS understands the relation between tuple elements:


const Parent = () => {
  const shouldRenderAndProps = useComponent(true);

  return (
    <>
      <div>Some Heading</div>
      {shouldRenderAndProps[0] && <Component {...shouldRenderAndProps[1]} />}
    </>
  )
}


Playground Link

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading