Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
OleksandrNechai opened this issue Sep 29, 2016 · 4 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@OleksandrNechai
Copy link

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.

@ahejlsberg
Copy link
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.

@ahejlsberg ahejlsberg added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Sep 29, 2016
@normalser
Copy link

normalser commented Sep 29, 2016

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 ;)

@OleksandrNechai
Copy link
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...

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Sep 29, 2016

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

5 participants