Skip to content

strictNullChecks still allows to assign undefined to the variable declared as number #11238

Description

TypeScript Version: 2.0.0

Code

// strictNullChecks is on
var x: number[] = [];
var y: number = x[0];
y.toString(); // Cannot read property 'toString' of undefined

Expected behavior:
error TS2322: Type 'undefined' is not assignable to type 'number'

Actual behavior:
after compile with command tsc --strictNullChecks
Runtime exception: Cannot read property 'toString' of undefined

I thought strictNullChecks a there to prevent developer from seeing such kind of exceptions in run time.

Activity

  1. ahejlsberg commented on Sep 29, 2016

    @ahejlsberg
    Member

    This is working as intended. We don't attempt to validate that array indexing operations produce existing elements; rather, we assume they always do. While this is technically not correct, the alternative of always adding undefined to the resulting type would simply be too painful. See discussion here. You could speculate that we could catch the issue in a few isolated cases (such as reading elements after assigning [] and before any elements are added), but it's not clear it is a common real world situation that would merit the effort to do so.

  2. normalser commented on Sep 29, 2016

    @normalser

    I would recommend adding this information to docs (handbook + what's new) because it's not the first time this issue is submitted to GitHub - and I guess people don't try to search in closed issues to find all the duplicates - and first thought is that this is in fact TS issue - and it's not easy to find that comment #7140 (comment) in Pull Request comments that explains that it's made for the convenience reason :)

    Or maybe --strictNullChecks=pain mode for the brave ones ;)

  3. OleksandrNechai commented on Sep 29, 2016

    @OleksandrNechai
    Author

    Ok, I see this is a tough problem. But for the end-user/programmer, it means that if my function, for example, accepts a number parameter I still must do guard checks whether it is undefined or not, even with --strictNullChecks, because my language does guaranty nothing. Probably I just don't understand the value proposition of strictNullChecks...

  4. RyanCavanaugh commented on Sep 29, 2016

    @RyanCavanaugh
    Member

    People don't search the docs either. 😢

    Consider the alternative universe where we did say you had to guard-off undefined in an array. Now every for loop looks like this:

    const arr = [1, 2, 3];
    for (let i = 0; i < arr.length; i++) {
      console.log('Element ' + i + ' has value ' + (arr[i]!).toFixed());
    }

    with the ! in there because the programmer thinks they've guarded against length. Then people are like "Why do I have to write ! after my array element accesses?" and the response is "So we can be sure you've thought about bounds checking", but the problem doesn't actually go away. I mean, no one just randomly accesses an element in an array without thinking about bounds. So instead you get a universe where every array element access is suffixed by ! as some meaningless ritual you have to do every time (which is annoying), but it's not actually linked to a proper bounds check in any concrete way.

    This doesn't actually help anyone. You can still write this

    const arr = [1, 2, 3];
    for (let i = 0; i <= arr.length; i++) {
      console.log('Element ' + i + ' has value ' + (arr[i]!).toFixed());
    }

    or

    const arr = [1, 2, 3];
    for (let i = 0; i < arr.length; i++) {
      console.log('Element ' + i + 
        ' has value ' + (arr[i]!).toFixed() + 
        ' and the next one is ' + (arr[i + 1]!).toFixed() );
    }

    or any other number of ways to get it wrong.

    You know how your car beeps at you if you don't have your seatbelt on? This is useful only because it can tell if you have your seatbelt on or not. A non-useful check would be that when you started the engine, you had to press a button that said "I have my seatbelt on". You'd immediately get into the habit of pressing that button regardless of whether you were actually buckled in. That's basically safety-by-EULA. Same here.

  5. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions