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) {...}

  • you mean instead of 
    class X

    I mean:

    function foo(i as Number) {
        var zc = ZONE_COLORS;
        if (zc != null) {
            var c = zc[i]; // Works!
        }
    }

    As far as I know, the type checker doesn't treat private variables any differently. As far as it's concerned, they could change out from under it at any moment. It's definitely less work to verify that that doesn't happen with privates, because you only have to analyze the owning class methods; but its essentially the same analysis you would have to do for public members/globals (ie it would require less compute time, but its essentially the same analysis).

  • I doubt this will decrease code since it'll add a new local variable

    But adding a new local is pretty cheap. 1 byte I think. And *using* a local is very cheap; something like 1 byte, rather than 4 for a non-local identifier. Which would mean the original used 8, and the modified used 1 + 4 + 1 + 1 = 7. But these numbers are guesses based on previous observations. When I just measured, I got a 2 byte difference, so...

    Actually, I think I *might* be mostly right about the sizes. Adding a new, uninitialized variable increases the code size by 1. But maybe thats the cost of initializing it to null. ie there's *no* cost to just declaring a variable. So declaring and initializing it to ZONE_COLORS may just be 4 bytes, rather than 1+4. In which case the numbers make sense.

  • Referencing:

    (:black_and_white)
    const ZONE_COLORS as Array<Graphics.ColorType> = null;
    (:color)
    const ZONE_COLORS = [-1 /*COLOR_TRANSPARENT*/, 0xAAAAAA /*COLOR_LT_GRAY*/, 0x00AAFF /*COLOR_BLUE*/, 0x00FF00 /*COLOR_GREEN*/,
    0xFF5500 /*COLOR_ORANGE*/, 0xFF0000 /*COLOR_RED*/, 0xAA0000 /*COLOR_DK_RED*/] as Array<Graphics.ColorType>;
    
    function foo(i as Number) {
      if (ZONE_COLORS != null) {
        var c = ZONE_COLORS[i]; // Attempting to perform container access on null.
      }
    }
    
    

    The problem is due to const implicit typing.

    If (:color) ZONE_COLORS is excluded, the compiler will error like above since it is implicitly typed as Null. If the code is updated so that a var is being defined rather than a const then ZONE_COLORS can be a Null (ZONE_COLORS as Array<Graphics.ColorType>?), and the error goes away.

    We're discussing whether a const should only implicitly type if there is not type a declaration, and looking at a couple of other related items. Regardless, we should at least warn if a const is defined as a type that does not match what it is being initialized to, so we'll look at getting that fixed.