7 ms·
The history of “typeof null” (2013)
- abdnafees 4y agoWhy even? Why don't they fix it?
- jwilk 4y agoSupposedly "because it would break existing code".
- tobr 4y ago> This is a bug and one that unfortunately can’t be fixed, because it would break existing code.
- 29athrowaway 4y agohttps://www.hyrumslaw.com/ https://www.hyrumslaw.com/
- fsckboy 4y agoLinus Torvalds has long had an ironclad rule, "don't break userspace" which sounds like the same thing from the hyrum's law link: With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.
- readthenotes1 4y ago"The difference between a bug and a feature is longevity." -said by someone last millennium
- bryanrasmussen 4y agothat's wrong, but it's been around so long I guess we have to accept it.
- abdnafees 4y agoAfter asking the question, I looked for an answer and found the is-object npm package. It utilizes a null check to make sure a variable is an object. This utility has 6.6 million weekly downloads. The logic in the isObject function will break because the second condition would then be invalidated. Resulting in a bad day for 6.6 million projects. It took me a while to digest the magnitude. Maybe because I just started as an SWE.
- andrewmackrodt 4y agoIf a language change were to update `typeof null` to return `"null"` isObject would not break, the second condition would only be unnecessary. However, other code which may make assertions on null values after checking the value is an object would break.
- white_dragon88 4y ago[dead]
- chrismorgan 4y agoYou drastically underestimate how much code depends on typeof null being "object". It’s extremely common in generic/library code. If you changed it to produce, say, "null", vast numbers of websites would completely break. As a simple example, a brief glance at the React and ReactDOM source code, inspecting the first few /typeof.*'object'/ matches, shows that in React, component.setState(null), and in ReactDOM, rendering class-based components with null state (which I’m guessing will be pretty much normal in existing code bases, even if it’s an older pattern now; but I haven’t ever used React seriously), would both throw an exception.
- bazoom42 4y agoExisting code might rely on this behavior, so if it changed some sites will stop working. Even if those sites were updated to the new behavior, browsers are not updated at the same time, so either way there would be a lot of breakage. And some sites will never be updated because they are not actively maintained.
- bryanrasmussen 4y agoI don't know that I buy the would break existing code - sure the language would change but do we actually have stats of uses where we can see people did.. what would they have done? if (typeof varname === "object" && !varname) { loggingNull("varname"); } it seems far fetched and maybe those people's code should break. I guess it doesn't really affect me though.
- jraph 4y agoIf my programming language changed something so fundamental, I would lose all trust in it even if I don't rely on this particular quirk. PL design is complicated and you pretty much have to keep this kind of quirks forever or at least for a very long time if you want to avoid a painful transition, which can lead to the old language version hanging out forever in the wild because a lot of code is already written in it. You can deprecate the features the quirks affect and introduce new ones to replace them that do not have the quirks, but now you need to support both ways for a very long time until the ecosystem is ready, which may never happen. there's nothing wrong with: switch (typeof v) { ... case ...: ... break; case "undefined": // handle undefined; break; case "object": if (!v) { // handle null; } else if (v instanceof 'Array') { // handle array; } else if (...) { ... } else { // handle anything else } break; } that's within spec and an alternative could be more verbose / more difficult to navigate (it's a matter of taste). If you need to handle undefined and null differently, you need to test for it and typeof === "object" is one way. I would probably do it differently, but I can see someone thinking differently and we can't blame them.
- aflag 4y ago"doesn't really affect me" until you find out one of the libraries you use is affected by it and you find yourself scrambling to fix it in production as new users update their browsers
- bryanrasmussen 4y agoI find, via experiences on HN, that language is a vague and irritating source of misunderstandings, but I thought it was clear that doesn't really affect me was because I was not going to use typeof in this way ever, thus I did not really care if it got 'fixed' or not.
- conaclos 4y agoI could like to have a kind of rust edition for JavaScript. You could opt in to an edition by adding a JavaScript directive at the start of the file — like the "use strict" directive. e.g. ```js "use edition2023" ``` This could enable to remove obsolete features and improve strictness. EDIT: I forgot the "use" before "strict".
- Vogtinator 4y agoThat's basically what "use strict" is, isn't it?
- conaclos 4y agoYep. We could then disable more feature and change some historical errors like "use strict" did.
- vasergen 4y agoI think it is a bit different, because with "use strict" we have already some rules and the typeof null is object there and now is too late to change that. The same for any other feature we don't want to have in a language. Maybe it was a mistake to introduce "use strict" without any other identifier, we need "use strict" with a version to be able to deprecate things and eventually remove from JS. Then JS engine could read it in the beginning of the file and know which version of js it is. Because in current JS we can only add new features without removing them. I am sure it is very complicated problem since we don't want to break the internet and browsers still have to work with old websites.
- deleted 4y ago[deleted]
- jraph 4y agoI've thought of something like that before for js. For this precise case, I guess the directive could forbid the use of typeof, or its use on null (and make it a runtime error). And your code ought to not accept values returned by typeof from foreign code, or to be careful with the "object" case. I don't think it can be a complete solution for making typeof return "null" for null for two reasons. 1) If you call f(typeof v) where f is defined in a module written in a different version, you are screwed. Contrived but within spec and we all know https://xkcd.com/1172/ https://xkcd.com/1172/ (if you didn't, now you do). 2) Moreover, old engines will ignore your directive and behave differently (return "object" instead of "null"), so now your code is incorrect depending on what engine runs it. In the end, it could as well be a linter rule that forces you to test v === null before calling typeof v and I think it would be the best option. If you care about this kind of stuff, you are probably already using a linter. The same kind of tool that complains about "==", which sets the same kind of traps, and you don't need to wait for something wrong to happen during execution, it's already warned statically before even running the code.