I hate to pile onto this extremely lengthy discussion, but I feel like I need to.
I realize this is a duplicate of #19066 and apropos of #10421.
For context, I'm working at Salesforce Quip (https://github.com/quip) on what will likely end up being a near year-long effort to transform roughly 500K lines of code of globally namespaced, Google Closure type-annotated JS to TypeScript -- using a custom transformation pipeline.
We've already converted the global namespace to ES6 modules and we've gotten the TSC error rate down below 10k.
The lack of something like flow's invariant or GCC's debug.assert is a problem. We have O(1000s) of calls to debug.assert() and the existing code was written such that GCC uses it as a type-refinement condition.
The thing that something like invariant accomplishes that #10421 would not (if I'm misunderstanding, please tell me) is that invariant allows you to run code.
This is important, because we have a system of diagnostic reporting in which client side errors are captured and submitted to tracking infrastructure on the server. Simply throwing isn't really an option. It's also the case, that in production, we actively do not want to stop execution when the condition fails. In many cases, the failed assertion wouldn't have resulted in user-visible failures.
I could imagine using the never type as workaround here, but it doesn't seem to cause type refinement in the same way that throw Error() does. e.g.
function foo(a: string | number): number {
if (typeof a === "string") {
unreached(); // Replace me with "throw new Error();" and this compiles
}
return a;
}
function unreached(): never {
throw new Error();
}
I hate to pile onto this extremely lengthy discussion, but I feel like I need to.
I realize this is a duplicate of #19066 and apropos of #10421.
For context, I'm working at Salesforce Quip (https://github.com/quip) on what will likely end up being a near year-long effort to transform roughly 500K lines of code of globally namespaced, Google Closure type-annotated JS to TypeScript -- using a custom transformation pipeline.
We've already converted the global namespace to ES6 modules and we've gotten the TSC error rate down below 10k.
The lack of something like flow's
invariantor GCC'sdebug.assertis a problem. We have O(1000s) of calls to debug.assert() and the existing code was written such that GCC uses it as a type-refinement condition.The thing that something like
invariantaccomplishes that #10421 would not (if I'm misunderstanding, please tell me) is that invariant allows you to run code.This is important, because we have a system of diagnostic reporting in which client side errors are captured and submitted to tracking infrastructure on the server. Simply throwing isn't really an option. It's also the case, that in production, we actively do not want to stop execution when the condition fails. In many cases, the failed assertion wouldn't have resulted in user-visible failures.
I could imagine using the
nevertype as workaround here, but it doesn't seem to cause type refinement in the same way thatthrow Error()does. e.g.