-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Allow equality comparisons to undefined and null in strict null checking mode #8452
Conversation
Fixes #8439. |
👍 |
@ahejlsberg would it be possible to automatically emit runtime checks at the "perimeter" of compiled TypeScript code? That is to say, exported functions/methods/etc with non-null parameters would have their arguments checked (in much the same way as you have manually coded above). Similarly return values from external function/method calls would also be checked, all seamlessly at runtime. This would effectively give a true runtime guarantee of non- Quite how you |
I have been thinking about this myself for a long time, but I avoided mentioning it as it seems like the team has shown strong aversion to run-time checks of any kind, however effective and desirable they are in practice for particular scenarios. I would like to highlight though, that argument checks are different in the sense that they should not be considered an "emit based on type information". The compiler doesn't generally assume any information on what it gets, as the analysis of calls is not generally contextual. The annotated type could be simply used as a key for a deterministic lookup into a list of predetermined and user-defined functions. I believe that is a very important point that must be made clear. If user-defined type guards were designed with reverse lookups in mind, it could have provided a tremendous benefit for libraries, especially those written particularly with plain JS consumers in mind. These checks could have been emitted conditionally based on a compiler switch or a pseudo-decorator annotation (or both). I don't believe that alternative solutions like decorators and reflective metadata would provide the level of elegance, user friendliness and sophistication that a built-in one would. Using decorators is essentially like requiring every developer to 'reinvent the wheel' in order to solve something that is generally well-defined and could have been easily automated. |
@malibuzios apologies, I don't really understand what you're getting at. To make concrete my suggestion, given the following exported function: // TypeScript - strictNullCheck
export function foo(obj: Object) {
// Do something with obj
} something like the following would be emitted: // emitted Javascript
define(["require", "exports"], function (require, exports) {
"use strict";
function foo(obj) {
if (obj == null) {
// NOTE the following error must _not_ be caught by any catch
throw new TypeError("Argument cannot be undefined or null");
}
// Do something with obj
}
exports.foo = foo;
}); Similarly for the following call to an external function: // TypeScript - strictNullCheck
import * as MyLib from "my-external-lib";
// As defined in someFile.d.ts
// MyLib.MyFunction(): string
let x = MyLib.MyFunction();
// Do something with x something like the following would be emitted: // emitted Javascript
define(["require", "exports", "my-external-lib"], function (require, exports, MyLib) {
"use strict";
// As defined in someFile.d.ts
// MyLib.MyFunction(): string
var x = MyLib.MyFunction();
if(x == null) {
// NOTE the following error must _not_ be caught by any catch
throw new TypeError("Return val cannot be undefined or null");
}
// Do something with x
}); |
I was referring to a more thorough and generalized runtime-checking solution that would go way beyond only checking for It could be assisted by user-defined guards as well. However, they were not designed with that in mind, to such a degree that many of them are not even suitable for run-time checks at all (including in decorators) as they encourage the programmer to apply unsound assumptions (there are many real-world examples of that people give here). Essentially promoting an 'indirect' emit on type information, although this may seem subtle. I'm sorry if I'm using overly technical concepts like 'emit on type information' and not giving enough examples. I think this may be content for a different issue. However, I don't feel much motivation to try to write a proposal as it seems very likely it would be (harshly, or even rudely) rejected. |
With this PR the
==
,!=
,===
, and!==
operators can be used to compare any type toundefined
ornull
in strict null checking mode. This makes it possible to practice "defensive coding" that checks for invalid arguments at run-time, for example:Even through TypeScript wouldn't permit
undefined
ornull
to be passed to the function, it may be useful to guard against invalid arguments passed from plain JavaScript code.