skip to Main Content

I’m new with Typescript and JavaScript and I’m not sure how to solve a situation on my React project.
I have this component below, but my onChange() line is not compiling. I receive a message saying this:

Type '((value: boolean) => void) | undefined' is not assignable to type '(value: boolean) => void'.
  Type 'undefined' is not assignable to type '(value: boolean) => void'.ts(2322)
ISelectUnselectAll.ts(3, 3): The expected type comes from property 'onChange' which is declared here on type 'IntrinsicAttributes & ISelectUnselectAll'
<SelectUnselectAll
  value={selectUnselectAll}
  disabled={!totalsStore.parsedList.length}
  onChange={onSelectUnselectAll}
  mode={'MENU'}
/>}

Actually I think the problem is because my onSelectUnselectAll function is coming by props from an interface when this function is optional. But I don’t know how to solve it.

export interface IExtraButtonsHeaderInvoiceTotals {
  onSelectUnselectAll?: (value: boolean) => void;

If I remove the ? the code compiles fine, but I can’t remove the ?.

I appreciate any help

3

Answers


  1. Chosen as BEST ANSWER

    Thanks, guys.

    The simplest solution was to check if my function is defined before rendering the component. The code looked like this:

    {onSelectUnselectAll &&
        <SelectUnselectAll
            value={selectUnselectAll}
            disabled={!totalsStore.parsedList.length}
            onChange={onSelectUnselectAll}
            mode={'MENU'}
         />
    }
    

    It's working fine now.


  2. Typescript purpose is to help with code maintenance and also to prevent possible errors that could happen in your application, that’s why that error pops up, ISelectUnselectAll is a contract which dictates exactly what you can pass to a your component, in that case, that contract says, onChange cannot be undefined, for whatever reason.

    When you add ? to a parameter it becomes possibly undefined and as you can see, the error says ((value: boolean) => void) | undefined) is not assignable to (value: boolean) => void, that means that the ISelectUnselectAll parameter onChange should always be defined.

    To solve this you could verify if the parameter exists before executing it, or remove ? making it a obligatory param and making sure that onSelectUnselectAll always is a function.

    const handleSelectUnselect = () => {
        if(onSelectUnselectAll) {
           onSelectUnselectAll()
        }
    } 
    
    <SelectUnselectAll
       value={selectUnselectAll}
       disabled={!totalsStore.parsedList.length}
       onChange={handleSelectUnselect}
       mode={'MENU'}
    />
    

    Also, you can simply add a ternary if, if your ESlint rules allow it:

    onChange={onSelectUnselectAll ?? onSelectUnselectAll()} 
    

    Also you could change the interface ISelectUnselectAll and let onChange be undefined

    interface ISelectUnselectAll {
       onChange: ((value: boolean) => void) | undefined)
    }
    
    Login or Signup to reply.
  3. You should decide what to do when it is undefined, and handle that case.

    Maybe the intent behind the original interface is that, if no function is provided, nothing is done, in which case the following should be correct. Here the function is passed if defined, and otherwise it is replaced by a default that does nothing.

    <SelectUnselectAll
      value={selectUnselectAll}
      disabled={!totalsStore.parsedList.length}
      onChange={onSelectUnselectAll ?? () => {}}
      mode={'MENU'}
    />
    

    Here is a working example.

    An alternative you should consider would be to have the default function log an error or throw an exception.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search