Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript/JSX Type Assertion works only outside JSX

I have a react component that maps through an array.

Each array item has an optional ID type.

If I have this ID, I will render an element, otherwise nothing.

This element has an onClick that calls a function accepts the ID as param.

Even though I check if I have the ID, TypeScript still complains that the ID might be undefined, but only inside the onClick method, not outside (see the code sample)

Why is that? How can I make this error go away?

Please see the error on the TypeScript playground:

enter image description here

// fake bindings
declare namespace React {
  function createElement(): any;
}

// This type has an optional prop
type SampleType = {
  id?: string;
  name: string;
}

const sampleArray: SampleType[] = [{id: 'test', name: 'Adrian'}, {name: 'Florescu'}]

function sampleFunction(id: string){
  console.log('ID', id);
}

function SampleComponent() {
  return (
    <div>
      {sampleArray.map((item: SampleType) => {
        if(item.id) {
          sampleFunction(item.id); // This works
          return <p onClick={() => { sampleFunction(item.id); }}>{item.name}</p>; //// This does not work
        }
      })}
    </div>
  )
};

const dom = <SampleComponent />;
like image 897
Adrian Florescu Avatar asked Jun 27 '19 11:06

Adrian Florescu


1 Answers

It's not JSX, it's timing. :-) Since the click happens later, it's entirely possible (from TypeScript's perspective) that id may have become undefined between when you checked it and when you are using it where a string is expected. The same thing would happen here:

setTimeout(() => {
  sampleFunction(item.id); // Same error occurs
}, 1000);

The solution is to make that not possible. One option is to capture id (and while we're there, we may as well capture name):

if(item.id) {
  const {id, name} = item;
  return <p onClick={() => { sampleFunction(id); }}>{name}</p>; // This works now
}

Updated playground

like image 190
T.J. Crowder Avatar answered Oct 05 '22 11:10

T.J. Crowder