#Is this a redundant check?

31 messages · Page 1 of 1 (latest)

fast slate
#

Hello, I am trying to understand why we need another check inside the render function. My code is below. You can see that I have the check to see if foo.bar is truthy as foo?.bar && from the beginning. However, why do I need another if check if(foo.bar) {...} in order to use foo.bar variable?
Another approach that seems to be working is to check foo and foo.bar individually such as: foo && foo.bar &&
Can someone explain to me with an example? Thank you very much 🙏

{ foo?.bar &&
<div className='field'>
<FormGroupField
name={barLabel ''}
id={"id-" + barLabel}
label={barLabel}
render={() => {
// If I place the return here without if(foo.bar), it errors out:
//return (<div>{utcToLocal(foo.bar).toLocaleString([], nativeJSDateFormat())}</div>)

            // I have to do this:
            if (foo.bar) {
                return (<div>{utcToLocal(foo.bar).toLocaleString([], nativeJSDateFormat())}</div>)
            }
        }}
    />
</div>

}

//Other solution is to replace foo?.bar && => foo && foo.bar && as in the next line:
{ foo && foo.bar &&
<div className='field'>
<FormGroupField
name={barLabel ''}
id={"id-" + barLabel}
label={barLabel}
render={() => {
// Then this is OK
return (<div>{utcToLocal(foo.bar).toLocaleString([], nativeJSDateFormat())}</div>)
}}
/>
</div>
}

#

@gray flume can you give me an example when the variable foo.bar can change?

#

and do you know why the TS compiler doesn't get mad when I have check: { foo && foo.bar && from the beginning? 🤔

unborn perch
#

can you give me an example when the variable foo.bar can change?

if (foo?.bar) {
  setTimeout(() => {
    console.log(foo.bar);
  }, 0);
  foo = undefined;
}
flat pierBOT
#
sandiford#0

Preview:```ts
const foo = {bar: 1} as {bar?: number} | undefined

if (foo?.bar) {
foo.bar
// ^?
delayed(() => {
console.log("function running")
foo.bar
// ^?
})
foo.bar = undefined
console.log("set bar to undefined")
}
...```

gray flume
#

Or what Jakob said

gray flume
fast slate
flat pierBOT
#
sandiford#0

Preview:```ts
import React from "react"

const foo = {bar: new Date()} as
| {bar: Date}
| undefined

const barLabel = "bar"

function utcToLocal(date: Date): Date {
return date
}

function Comp() {
//Other solution is to replace foo?.bar && => foo && foo.bar && as in the next line:
return (
<>
{foo && foo.bar && (
...```

gray flume
#

it's nearly there

#

I don't see to get errors with either way...

#

TS doesn't always handle things strictly correctly, so it's possible that it chooses not to invalidate

fast slate
#

ya, my co-worker and I have an argument about this over a Pull Request. I said the inner if-check is redundant, and he said it's not.

#

so, motivate me to know how it actually works

gray flume
#

Well, first issue is that we can't reproduce it

#

so is it specific to your TS version or config?

#

You can click TS Config at the top on playground, and change TS version, to try to figure that out

#

If this component updates and the value of foo changes, then you could find that this code errors without the second check

fast slate
#

let me test some more

#

so, if I have the check: { foo?.bar && ... }
is it possible that foo or bar are undefined and still pass this check?

gray flume
#

I don't think so

gray flume
#

If the main component updates, then it will update the child, so that would be OK

signal ice
#

@fast slate The issue is that the check is across a function boundary

#

Ah yeah, Bert said this in #ts-discussion before it moved here.

#

The usual fix is to move the thing you're narrowing into a const.

#
const fooBar = foo?.bar;
fooBar && /* ... can safely assume fooBar is defined in here, even inside a function */ 
fast slate
#

After looking into the code further, I think the problem is that the function utcToLocal take the input type of string | Date, but foo.bar has the type of string | undefined. Looks like the check if(foo.bar) convert it to string type, without it, it causes error:
Argument of type 'string | undefined' is not assignable to parameter of type 'string | Date'.
Type 'undefined' is not assignable to type 'string | Date'. TS2345

fast slate
#

I think I understand why now. The scope of the outer check doesn't cover the scope of the anonymous function in the render field. This is why we have to do the validation again. Thanks, everyone for your responses and help.

#

We can change this to resolved 🙂

gray flume
#

!resolved