Type Check Level: strict causes Cannot find symbol ':data' on type 'Null'

Wen I set the Type Check Level to strinct then the following code doesn't compile:

if (sensor != null && sensor.data != null) {...}

Type Check Level: strict causes Cannot find symbol ':data' on type 'Null'

How am I supposed to deal with these? Is there a better solution than the too verbose casting:

if (sensor != null && (sensor as Sensor).data != null) {...}

The compiler must be clever enough to figure it out that sensor can't be null there, or at least we should have the ! operator like in kotlin:

if (sensor != null && sensor!.data != null) {...}

  • That's pre-compile and not runtime or even the compiler.  Monkey Types has no runtime elements.

    You want to avoid this, turn off type checking or figure out why Monkey Types is complaining

  • It's complaining because it's stupid. sensor is declared as Sensor?, but that's exactly the reason why the 1st thing I check is if it's null:

        function compute(sensor as Sensor?) as Boolean {
            if (sensor != null && sensor.data != null) {

  • I've reported this before. For unknown reasons, the typechecker doesn't treat && as short circuit. So you *can* say

    if (sensor != null) { if (sensor.data != null) {...} }

    but it tends to get clunky. You might be able to do a bit better (save one level of {}) by doing

    if (sensor == null) {} else if (sensor.data != null) {...}

    The other alternative is that it *does* treat ?: as short circuiting, so you can also do

    if (sensor != null ? sensor.data != null : false) {...}

    but again, with more complex expressions it can start getting painful.

  • Yeah, if all other compilers are clever enough to know about: x != null && x.foo, then I hope Garmin will teach the monkey. Or at least give us a syntactic sugar : x != null && x!.foo. I don't mind adding 1 extra !. It would mean the same type(s) as it's declared - null

  • It might be related to https://forums.garmin.com/developer/connect-iq/i/bug-reports/strange-behavior-of-logical-operators, but that shouldn't be an issue when the lhs of the && is actually a boolean expression. And since they handle ?: correctly there's really no reason they shouldn't handle && correctly too.

    But the whole thing is a mess. There are lots of inconsistencies, and lots of missing features.

  • For me, I'd concentrate on getting things working without Monkey Types used in the code or the compile.

    Then spend time with types to see if it's your code, the source code, or CIQ that's causing issues. 

    There is a ton of code on places like github that doesn't use Monkey Types you can test with.

  • After some discussion, we've determined this has already been fixed but hasn't been made available in a public release yet. I expect it fixes will be available in a release later this month. FWIW, we've already been talking about doing something like the '!' suggested in this thread.

  • I expect it fixes will be available in a release later this month

    4.1.4 just dropped, and it's not fixed there.

    I'm definitely using the new sdk:

    > Executing task: java -Xms1g -Dfile.encoding=UTF-8 -Dapple.awt.UIElement=true -jar /Users/mwilliams/Library/Application Support/Garmin/ConnectIQ/Sdks/connectiq-sdk-mac-4.1.4-2022-06-07-f86da2dee/bin/monkeybrains.jar ...

    But I get:

    ERROR: approachs60: layouts.mc:97: Cannot perform operation 'gte' on types 'PolyType<Null or $.Toybox.Lang.Object>' and '$.Toybox.Lang.Number'.

    The offending line is:

    s.hrOption =
       hrOpt instanceof Lang.Number && hrOpt >= -5 && hrOpt < 8 ? hrOpt : 0;
    It works if I change it to:
    s.hrOption =
      hrOpt instanceof Lang.Number ? hrOpt >= -5 && hrOpt < 8 ? hrOpt : 0 : 0;
    ie ?: propagates type inference info, but && does not.
  • s.hrOption =

      hrOpt instanceof Lang.Number ? (hrOpt >= -5 && hrOpt < 8 ? hrOpt : 0) : 0;

  • Well it's only 10th June, maybe they plan another release before July ;)