3 ms·
I know how it works. I'm talking about practical implications. In practice, say I have type User = { name: string, email: string } let loggedInUser:
by realharo 6y ago
I know how it works. I'm talking about practical implications.
In practice, say I have
type User = { name: string, email: string }
let loggedInUser: User = { name: 'Bob', email: 'bob@examaple.com' }
or even
// Can't change the contents, only reassign the whole variable
let loggedInUser: Readonly<User> = ...
and only ever use that `loggedInUser` from TypeScript code (because my entire codebase is TypeScript), and I avoid the 3 scenarios mentioned above (buggy JS library type definitions, non-validated external data, casting/any/`!`).
How would a `null` email ever get inside `loggedInUser`? It just won't happen. I know there are no run-time checks - I don't need any run-time checks. I don't need 100% theoretical guarantees. I can be reasonably certain that `loggedInUser.email` will always be a non-null non-undefined string. It's a good enough™ practical guarantee. A null-check on `loggedInUser.email` would be pure confusing noise (because anyone reading it would go "wait, this can be null? I thought it was non-null").
Do you have a practical explanation of how a `loggedInUser.email === null` situation might occur given the above assumptions?
>Given any JS variable can be assigned both `undefined` and `null`
Any JS variable can be assigned literally anything. I don't need to check that `loggedInUser.email` is not null, just like I don't need to check that `loggedInUser.email` is not a boolean or a number. Because how would that even happen? Not having to do those checks is half the point of having a static type system in the first place (the other half is being notified of type errors at compile/edit time).
If you need to defensively check whether something so basic that is never supposed to happen has happened, then the code is already a giant unmaintainable mess.
- realharo 6y agoTo sort of answer my own question, there is one more "leak" I forgot about - array bounds are unchecked https://github.com/Microsoft/TypeScript/issues/11122 https://github.com/Microsoft/TypeScript/issues/11122, which can give you `undefined` (though not `null`) without it being reflected in the type of the expression. Similar for objects with arbitrary keys (i.e. maps/dictionaries/etc.) https://github.com/microsoft/TypeScript/issues/13778 https://github.com/microsoft/TypeScript/issues/13778. E.g. `const a = [1, 2, 3]` will let you do `a[5]` and still give it type `number` instead of `number|undefined` as mentioned in the github issue. Many other languages also do this (though they have runtime checks/errors). So that kinda sucks, but the rest still stands (there is still no practically realistic way for `null` or anything other than `undefined` to get there). Hopefully they'll fix that in the future with a new compiler setting.