Why doesn't logical OR work with error throwing in JavaScript?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







47















This is a pretty common and useful practice:



// default via value
var un = undefined
var v1 = un || 1

// default via a function call
var myval = () => 1
var v2 = un || myval()


But it doesn't work (SyntaxError) when throwing an error:



var v3 = un || throw new Error('un is not set!')


Is there a way how to achieve the same effect in a similarly elegant way?
This is IMHO a lot of boilerplate code:



if (!un) {
throw new Error('un is not set!')
}
var v3 = un


Or is there any theoretical obstruction, why this is not, and never will be, possible?










share|improve this question

























  • This looks a lot like PHP (or Ruby?) where you it's common practice to do something similar $dbHandle = connectToDB() OR die("couldn't connect"). Still, I can't recall if PHP allowed throw statements as part of that construct.

    – VLAZ
    Feb 11 at 15:23






  • 2





    @VLAZ die() looks like a function. A function is an expression in JavaScript as well.

    – ttulka
    Feb 11 at 15:41






  • 1





    Sure, but I'm talking about the general patter of "error in one line". It reminds me a lot of how you'd do that in PHP - the do() OR die() was very common, at least back when I wrote PHP. Trying to throw an exception in the same line as another expression strikes me as the same patter.

    – VLAZ
    Feb 11 at 15:50






  • 3





    In addition to the answers: there is a proposal for this to be possible, so maybe soon we will have throw expressions.

    – vsemozhetbyt
    Feb 11 at 19:14








  • 1





    @vsemozhetbyt Thanks for the comment, this is the actual answer to my question!

    – ttulka
    Feb 12 at 6:58


















47















This is a pretty common and useful practice:



// default via value
var un = undefined
var v1 = un || 1

// default via a function call
var myval = () => 1
var v2 = un || myval()


But it doesn't work (SyntaxError) when throwing an error:



var v3 = un || throw new Error('un is not set!')


Is there a way how to achieve the same effect in a similarly elegant way?
This is IMHO a lot of boilerplate code:



if (!un) {
throw new Error('un is not set!')
}
var v3 = un


Or is there any theoretical obstruction, why this is not, and never will be, possible?










share|improve this question

























  • This looks a lot like PHP (or Ruby?) where you it's common practice to do something similar $dbHandle = connectToDB() OR die("couldn't connect"). Still, I can't recall if PHP allowed throw statements as part of that construct.

    – VLAZ
    Feb 11 at 15:23






  • 2





    @VLAZ die() looks like a function. A function is an expression in JavaScript as well.

    – ttulka
    Feb 11 at 15:41






  • 1





    Sure, but I'm talking about the general patter of "error in one line". It reminds me a lot of how you'd do that in PHP - the do() OR die() was very common, at least back when I wrote PHP. Trying to throw an exception in the same line as another expression strikes me as the same patter.

    – VLAZ
    Feb 11 at 15:50






  • 3





    In addition to the answers: there is a proposal for this to be possible, so maybe soon we will have throw expressions.

    – vsemozhetbyt
    Feb 11 at 19:14








  • 1





    @vsemozhetbyt Thanks for the comment, this is the actual answer to my question!

    – ttulka
    Feb 12 at 6:58














47












47








47


3






This is a pretty common and useful practice:



// default via value
var un = undefined
var v1 = un || 1

// default via a function call
var myval = () => 1
var v2 = un || myval()


But it doesn't work (SyntaxError) when throwing an error:



var v3 = un || throw new Error('un is not set!')


Is there a way how to achieve the same effect in a similarly elegant way?
This is IMHO a lot of boilerplate code:



if (!un) {
throw new Error('un is not set!')
}
var v3 = un


Or is there any theoretical obstruction, why this is not, and never will be, possible?










share|improve this question
















This is a pretty common and useful practice:



// default via value
var un = undefined
var v1 = un || 1

// default via a function call
var myval = () => 1
var v2 = un || myval()


But it doesn't work (SyntaxError) when throwing an error:



var v3 = un || throw new Error('un is not set!')


Is there a way how to achieve the same effect in a similarly elegant way?
This is IMHO a lot of boilerplate code:



if (!un) {
throw new Error('un is not set!')
}
var v3 = un


Or is there any theoretical obstruction, why this is not, and never will be, possible?







javascript






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 12 at 6:56







ttulka

















asked Feb 11 at 7:52









ttulkattulka

2,65511627




2,65511627













  • This looks a lot like PHP (or Ruby?) where you it's common practice to do something similar $dbHandle = connectToDB() OR die("couldn't connect"). Still, I can't recall if PHP allowed throw statements as part of that construct.

    – VLAZ
    Feb 11 at 15:23






  • 2





    @VLAZ die() looks like a function. A function is an expression in JavaScript as well.

    – ttulka
    Feb 11 at 15:41






  • 1





    Sure, but I'm talking about the general patter of "error in one line". It reminds me a lot of how you'd do that in PHP - the do() OR die() was very common, at least back when I wrote PHP. Trying to throw an exception in the same line as another expression strikes me as the same patter.

    – VLAZ
    Feb 11 at 15:50






  • 3





    In addition to the answers: there is a proposal for this to be possible, so maybe soon we will have throw expressions.

    – vsemozhetbyt
    Feb 11 at 19:14








  • 1





    @vsemozhetbyt Thanks for the comment, this is the actual answer to my question!

    – ttulka
    Feb 12 at 6:58



















  • This looks a lot like PHP (or Ruby?) where you it's common practice to do something similar $dbHandle = connectToDB() OR die("couldn't connect"). Still, I can't recall if PHP allowed throw statements as part of that construct.

    – VLAZ
    Feb 11 at 15:23






  • 2





    @VLAZ die() looks like a function. A function is an expression in JavaScript as well.

    – ttulka
    Feb 11 at 15:41






  • 1





    Sure, but I'm talking about the general patter of "error in one line". It reminds me a lot of how you'd do that in PHP - the do() OR die() was very common, at least back when I wrote PHP. Trying to throw an exception in the same line as another expression strikes me as the same patter.

    – VLAZ
    Feb 11 at 15:50






  • 3





    In addition to the answers: there is a proposal for this to be possible, so maybe soon we will have throw expressions.

    – vsemozhetbyt
    Feb 11 at 19:14








  • 1





    @vsemozhetbyt Thanks for the comment, this is the actual answer to my question!

    – ttulka
    Feb 12 at 6:58

















This looks a lot like PHP (or Ruby?) where you it's common practice to do something similar $dbHandle = connectToDB() OR die("couldn't connect"). Still, I can't recall if PHP allowed throw statements as part of that construct.

– VLAZ
Feb 11 at 15:23





This looks a lot like PHP (or Ruby?) where you it's common practice to do something similar $dbHandle = connectToDB() OR die("couldn't connect"). Still, I can't recall if PHP allowed throw statements as part of that construct.

– VLAZ
Feb 11 at 15:23




2




2





@VLAZ die() looks like a function. A function is an expression in JavaScript as well.

– ttulka
Feb 11 at 15:41





@VLAZ die() looks like a function. A function is an expression in JavaScript as well.

– ttulka
Feb 11 at 15:41




1




1





Sure, but I'm talking about the general patter of "error in one line". It reminds me a lot of how you'd do that in PHP - the do() OR die() was very common, at least back when I wrote PHP. Trying to throw an exception in the same line as another expression strikes me as the same patter.

– VLAZ
Feb 11 at 15:50





Sure, but I'm talking about the general patter of "error in one line". It reminds me a lot of how you'd do that in PHP - the do() OR die() was very common, at least back when I wrote PHP. Trying to throw an exception in the same line as another expression strikes me as the same patter.

– VLAZ
Feb 11 at 15:50




3




3





In addition to the answers: there is a proposal for this to be possible, so maybe soon we will have throw expressions.

– vsemozhetbyt
Feb 11 at 19:14







In addition to the answers: there is a proposal for this to be possible, so maybe soon we will have throw expressions.

– vsemozhetbyt
Feb 11 at 19:14






1




1





@vsemozhetbyt Thanks for the comment, this is the actual answer to my question!

– ttulka
Feb 12 at 6:58





@vsemozhetbyt Thanks for the comment, this is the actual answer to my question!

– ttulka
Feb 12 at 6:58












5 Answers
5






active

oldest

votes


















78














throw is a statement only; it may not exist in a position where an expression is required. For similar reasons, you can't put an if statement there, for example



var something = false || if (cond) { /* something */ }


is invalid syntax as well.



Only expressions (things that evaluate to a value) are permitted to be assigned to variables. If you want to throw, you have to throw as a statement, which means you can't put it on the right-hand side of an assignment.



I suppose one way would be to use an IIFE on the right-hand side of the ||, allowing you to use a statement on the first line of that function:






var un = undefined
var v2 = un || (() => { throw new Error('nope') })();





But that's pretty weird. I'd prefer the explicit if - throw.






share|improve this answer



















  • 3





    It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

    – usr
    Feb 11 at 19:47






  • 3





    In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

    – Ben Blank
    Feb 11 at 20:08






  • 3





    Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

    – KRyan
    Feb 12 at 4:57



















32














Your problem is that an assignment expects an expression but you give it a statement



The Syntax for initializing/assigning a variable is:



var|let|const <variableName> = <expression>


but you use



var|let|const <variableName> = <statement>


which is invalid Syntax.



Expressions



An expression is something that produces a value.



What is a "value"?



A value is anything that is a type in Javascript




  • Numbers

  • Strings

  • Booleans

  • Objects

  • Arrays

  • Symbols


Examples for Expressions:



Literals



var x = 5;


x is assigned the value "5"



A function call



var x = myFunc();


myFunc() produces a value that is assigned to x



The produced value of a function is its return value - A function always returns, and if it doesn't explicitly, it returns undefined.



Functions have the added benefit of being able to contain statements in their body - Which will be the solution to your question - But more on that later.



Statements



A statement is something that performs an action. For Example:



A loop



for (var i = 0; i < 10; i++) { /* loop body */ }


This loop performs the action of executing the loop body 10 times



Throwing an error



throw new Error()


Unwinds the stack and stops the execution of the current frame



So why can't we mix both?



When you want to assign to a variable, you want an expression because you want the variable to have a value.



If you think about it, it should be clear that it will never work with a statement. Giving a variable an "action" is nonsense. What is that even supposed to mean?



Therefore you cannot use the throw statement since it does not produce a value.



You can only have one or the other.
Either you are (expression) something or you do (statement) something.



A fix



You can convert any statement into an expression by wrapping it in a function, I suggest using an IIFE (Immediately invoked function expression) - basically a function that invokes itself - to do just that



var x = 5 || (() => throw new Error())()


This works because the right side is now a function and a function is an expression which produces a value.



Future Possibilities



Technically there is nothing that prevents this from working.



Many languages (c++, ...) actually already treat throw as an expression. Some (kotlin, ...) even leave out statements completely and treat everything as an expression.



Others (c#, php, ...) provide workarounds like the ?? null-concealing or ?. elvis operator to solve this very use case.



Maybe in the future we get one of those features into the ecmascript standard (there is even an open proposal to include this) until then your best bet is to use a function like:



function assertPresent(value, message)
{
if(!value) {
throw new Error(message);
} else {
return value;
}
}





share|improve this answer





















  • 5





    As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

    – TheHansinator
    Feb 11 at 13:54











  • Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

    – jcaron
    Feb 11 at 17:37






  • 1





    It's also an expression (of type void) in C++.

    – The Vee
    Feb 11 at 18:13



















19














You could move the throwing of the exception into a function, because throw is a statement of control flow, and not an expression:




An expression is any valid unit of code that resolves to a value.







const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');








share|improve this answer





















  • 7





    Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

    – Dan Robertson
    Feb 11 at 10:09






  • 1





    Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

    – T.J. Crowder
    Feb 12 at 10:14





















3














As other answers have stated, it is because throw is a statement, which can't be used in contexts which expect expressions, such as on the right side of a ||. As stated by others, you can get around that by wrapping the exception in a function and immediately calling it, but I'm going to make the case that doing so is a bad idea because it makes your intent less clear. Three extra lines of code is not a big deal for making the intent of your code very clear and explicit. I personally think that throw being statement-only is a good thing because it encourages writing more straightforward code that is less likely to cause other developers to scratch their heads when encountering your code.



The || defaulting idiom is useful when you want to provide default or alternative values for undefined, null, and other falsy values, but I think it loses a lot of its clarity when used in a branching sense. By "branching sense", I mean that if your intent is to do something if a condition holds (the doing something in this case being throwing an exception), then condition || do_something() is really not a clear way to express that intent even though it is functionally identical to if (!condition) {do_something()}. Short-circuit evaluation isn't immediately obvious to every developer and || defaulting is only understood because it's a commonly-used idiom in Javascript.



My general rule of thumb is that if a function has side effects (and yes, exceptions count as side effects, especially since they're basically non-local goto statements), you should use an if statement for its condition rather than || or &&. You're not golfing.



Bottom line: which is going to cause less confusion?



return value || (() => {throw new Error('an error occurred')})()


or



if (!value) {
throw new Error('an error occurred')
}
return value


It's usually worth it to sacrifice terseness for clarity.






share|improve this answer



















  • 1





    An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

    – ttulka
    Feb 12 at 6:55






  • 1





    @ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

    – Beefster
    Feb 12 at 7:57






  • 1





    And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

    – Beefster
    Feb 12 at 8:04






  • 1





    I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

    – ttulka
    Feb 12 at 8:46






  • 1





    An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

    – Beefster
    Feb 12 at 8:51



















1














Like others have said the problem is that throw is a statement and not an expression.



There is however really no need for this dichotomy. There are languages where everything is an expression (no statements) and they're not "inferior" because of this; it simplifies both syntax and semantic (e.g. you don't need separate if statements and the ternary operator ?:).



Actually this is just one of the many reasons for which Javascript (the language) kind of sucks, despite Javascript (the runtime environment) being amazing.



A simple work-around (that can be used also in other languages with a similar limitation like Python) is:



function error(x) { throw Error(x); }


then you can simply write



let x = y.parent || error("No parent");


There is some complexity in having throw as an expression for statically typed languages: what should be the static type of x() ? y() : throw(z)?; for example C++ has a very special rule for handling a throw expression in the ternary operator (the type is taken from the other branch, even if formally throw x is considered an expression of type void).






share|improve this answer





















  • 2





    Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

    – Cristik
    Feb 14 at 0:30












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54626074%2fwhy-doesnt-logical-or-work-with-error-throwing-in-javascript%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























5 Answers
5






active

oldest

votes








5 Answers
5






active

oldest

votes









active

oldest

votes






active

oldest

votes









78














throw is a statement only; it may not exist in a position where an expression is required. For similar reasons, you can't put an if statement there, for example



var something = false || if (cond) { /* something */ }


is invalid syntax as well.



Only expressions (things that evaluate to a value) are permitted to be assigned to variables. If you want to throw, you have to throw as a statement, which means you can't put it on the right-hand side of an assignment.



I suppose one way would be to use an IIFE on the right-hand side of the ||, allowing you to use a statement on the first line of that function:






var un = undefined
var v2 = un || (() => { throw new Error('nope') })();





But that's pretty weird. I'd prefer the explicit if - throw.






share|improve this answer



















  • 3





    It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

    – usr
    Feb 11 at 19:47






  • 3





    In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

    – Ben Blank
    Feb 11 at 20:08






  • 3





    Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

    – KRyan
    Feb 12 at 4:57
















78














throw is a statement only; it may not exist in a position where an expression is required. For similar reasons, you can't put an if statement there, for example



var something = false || if (cond) { /* something */ }


is invalid syntax as well.



Only expressions (things that evaluate to a value) are permitted to be assigned to variables. If you want to throw, you have to throw as a statement, which means you can't put it on the right-hand side of an assignment.



I suppose one way would be to use an IIFE on the right-hand side of the ||, allowing you to use a statement on the first line of that function:






var un = undefined
var v2 = un || (() => { throw new Error('nope') })();





But that's pretty weird. I'd prefer the explicit if - throw.






share|improve this answer



















  • 3





    It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

    – usr
    Feb 11 at 19:47






  • 3





    In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

    – Ben Blank
    Feb 11 at 20:08






  • 3





    Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

    – KRyan
    Feb 12 at 4:57














78












78








78







throw is a statement only; it may not exist in a position where an expression is required. For similar reasons, you can't put an if statement there, for example



var something = false || if (cond) { /* something */ }


is invalid syntax as well.



Only expressions (things that evaluate to a value) are permitted to be assigned to variables. If you want to throw, you have to throw as a statement, which means you can't put it on the right-hand side of an assignment.



I suppose one way would be to use an IIFE on the right-hand side of the ||, allowing you to use a statement on the first line of that function:






var un = undefined
var v2 = un || (() => { throw new Error('nope') })();





But that's pretty weird. I'd prefer the explicit if - throw.






share|improve this answer













throw is a statement only; it may not exist in a position where an expression is required. For similar reasons, you can't put an if statement there, for example



var something = false || if (cond) { /* something */ }


is invalid syntax as well.



Only expressions (things that evaluate to a value) are permitted to be assigned to variables. If you want to throw, you have to throw as a statement, which means you can't put it on the right-hand side of an assignment.



I suppose one way would be to use an IIFE on the right-hand side of the ||, allowing you to use a statement on the first line of that function:






var un = undefined
var v2 = un || (() => { throw new Error('nope') })();





But that's pretty weird. I'd prefer the explicit if - throw.






var un = undefined
var v2 = un || (() => { throw new Error('nope') })();





var un = undefined
var v2 = un || (() => { throw new Error('nope') })();






share|improve this answer












share|improve this answer



share|improve this answer










answered Feb 11 at 7:57









CertainPerformanceCertainPerformance

99k166089




99k166089








  • 3





    It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

    – usr
    Feb 11 at 19:47






  • 3





    In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

    – Ben Blank
    Feb 11 at 20:08






  • 3





    Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

    – KRyan
    Feb 12 at 4:57














  • 3





    It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

    – usr
    Feb 11 at 19:47






  • 3





    In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

    – Ben Blank
    Feb 11 at 20:08






  • 3





    Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

    – KRyan
    Feb 12 at 4:57








3




3





It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

– usr
Feb 11 at 19:47





It's worth pointing out that throw could have been made an expression. Maybe a future language version will enable this pattern.

– usr
Feb 11 at 19:47




3




3





In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

– Ben Blank
Feb 11 at 20:08





In fact, there's already a stage 2 proposal to add throw expressions to the language. Alas, it'll still be a while before it's available for use.

– Ben Blank
Feb 11 at 20:08




3




3





Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

– KRyan
Feb 12 at 4:57





Our project—in Typescript, so the pattern is perhaps more transparent—we have a core utility module that includes export function crash(message: string): never { throw new Error(message); } and all throws are done via this function. Useful because now it’s an expression (and the never return annotation indicates it won’t return because it throws), and because we can put a breakpoint in it (we have a high-level catch block to produce a custom error message rather than it merely being sent to the console, but this can prevent the debugger from breaking on the throw).

– KRyan
Feb 12 at 4:57













32














Your problem is that an assignment expects an expression but you give it a statement



The Syntax for initializing/assigning a variable is:



var|let|const <variableName> = <expression>


but you use



var|let|const <variableName> = <statement>


which is invalid Syntax.



Expressions



An expression is something that produces a value.



What is a "value"?



A value is anything that is a type in Javascript




  • Numbers

  • Strings

  • Booleans

  • Objects

  • Arrays

  • Symbols


Examples for Expressions:



Literals



var x = 5;


x is assigned the value "5"



A function call



var x = myFunc();


myFunc() produces a value that is assigned to x



The produced value of a function is its return value - A function always returns, and if it doesn't explicitly, it returns undefined.



Functions have the added benefit of being able to contain statements in their body - Which will be the solution to your question - But more on that later.



Statements



A statement is something that performs an action. For Example:



A loop



for (var i = 0; i < 10; i++) { /* loop body */ }


This loop performs the action of executing the loop body 10 times



Throwing an error



throw new Error()


Unwinds the stack and stops the execution of the current frame



So why can't we mix both?



When you want to assign to a variable, you want an expression because you want the variable to have a value.



If you think about it, it should be clear that it will never work with a statement. Giving a variable an "action" is nonsense. What is that even supposed to mean?



Therefore you cannot use the throw statement since it does not produce a value.



You can only have one or the other.
Either you are (expression) something or you do (statement) something.



A fix



You can convert any statement into an expression by wrapping it in a function, I suggest using an IIFE (Immediately invoked function expression) - basically a function that invokes itself - to do just that



var x = 5 || (() => throw new Error())()


This works because the right side is now a function and a function is an expression which produces a value.



Future Possibilities



Technically there is nothing that prevents this from working.



Many languages (c++, ...) actually already treat throw as an expression. Some (kotlin, ...) even leave out statements completely and treat everything as an expression.



Others (c#, php, ...) provide workarounds like the ?? null-concealing or ?. elvis operator to solve this very use case.



Maybe in the future we get one of those features into the ecmascript standard (there is even an open proposal to include this) until then your best bet is to use a function like:



function assertPresent(value, message)
{
if(!value) {
throw new Error(message);
} else {
return value;
}
}





share|improve this answer





















  • 5





    As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

    – TheHansinator
    Feb 11 at 13:54











  • Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

    – jcaron
    Feb 11 at 17:37






  • 1





    It's also an expression (of type void) in C++.

    – The Vee
    Feb 11 at 18:13
















32














Your problem is that an assignment expects an expression but you give it a statement



The Syntax for initializing/assigning a variable is:



var|let|const <variableName> = <expression>


but you use



var|let|const <variableName> = <statement>


which is invalid Syntax.



Expressions



An expression is something that produces a value.



What is a "value"?



A value is anything that is a type in Javascript




  • Numbers

  • Strings

  • Booleans

  • Objects

  • Arrays

  • Symbols


Examples for Expressions:



Literals



var x = 5;


x is assigned the value "5"



A function call



var x = myFunc();


myFunc() produces a value that is assigned to x



The produced value of a function is its return value - A function always returns, and if it doesn't explicitly, it returns undefined.



Functions have the added benefit of being able to contain statements in their body - Which will be the solution to your question - But more on that later.



Statements



A statement is something that performs an action. For Example:



A loop



for (var i = 0; i < 10; i++) { /* loop body */ }


This loop performs the action of executing the loop body 10 times



Throwing an error



throw new Error()


Unwinds the stack and stops the execution of the current frame



So why can't we mix both?



When you want to assign to a variable, you want an expression because you want the variable to have a value.



If you think about it, it should be clear that it will never work with a statement. Giving a variable an "action" is nonsense. What is that even supposed to mean?



Therefore you cannot use the throw statement since it does not produce a value.



You can only have one or the other.
Either you are (expression) something or you do (statement) something.



A fix



You can convert any statement into an expression by wrapping it in a function, I suggest using an IIFE (Immediately invoked function expression) - basically a function that invokes itself - to do just that



var x = 5 || (() => throw new Error())()


This works because the right side is now a function and a function is an expression which produces a value.



Future Possibilities



Technically there is nothing that prevents this from working.



Many languages (c++, ...) actually already treat throw as an expression. Some (kotlin, ...) even leave out statements completely and treat everything as an expression.



Others (c#, php, ...) provide workarounds like the ?? null-concealing or ?. elvis operator to solve this very use case.



Maybe in the future we get one of those features into the ecmascript standard (there is even an open proposal to include this) until then your best bet is to use a function like:



function assertPresent(value, message)
{
if(!value) {
throw new Error(message);
} else {
return value;
}
}





share|improve this answer





















  • 5





    As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

    – TheHansinator
    Feb 11 at 13:54











  • Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

    – jcaron
    Feb 11 at 17:37






  • 1





    It's also an expression (of type void) in C++.

    – The Vee
    Feb 11 at 18:13














32












32








32







Your problem is that an assignment expects an expression but you give it a statement



The Syntax for initializing/assigning a variable is:



var|let|const <variableName> = <expression>


but you use



var|let|const <variableName> = <statement>


which is invalid Syntax.



Expressions



An expression is something that produces a value.



What is a "value"?



A value is anything that is a type in Javascript




  • Numbers

  • Strings

  • Booleans

  • Objects

  • Arrays

  • Symbols


Examples for Expressions:



Literals



var x = 5;


x is assigned the value "5"



A function call



var x = myFunc();


myFunc() produces a value that is assigned to x



The produced value of a function is its return value - A function always returns, and if it doesn't explicitly, it returns undefined.



Functions have the added benefit of being able to contain statements in their body - Which will be the solution to your question - But more on that later.



Statements



A statement is something that performs an action. For Example:



A loop



for (var i = 0; i < 10; i++) { /* loop body */ }


This loop performs the action of executing the loop body 10 times



Throwing an error



throw new Error()


Unwinds the stack and stops the execution of the current frame



So why can't we mix both?



When you want to assign to a variable, you want an expression because you want the variable to have a value.



If you think about it, it should be clear that it will never work with a statement. Giving a variable an "action" is nonsense. What is that even supposed to mean?



Therefore you cannot use the throw statement since it does not produce a value.



You can only have one or the other.
Either you are (expression) something or you do (statement) something.



A fix



You can convert any statement into an expression by wrapping it in a function, I suggest using an IIFE (Immediately invoked function expression) - basically a function that invokes itself - to do just that



var x = 5 || (() => throw new Error())()


This works because the right side is now a function and a function is an expression which produces a value.



Future Possibilities



Technically there is nothing that prevents this from working.



Many languages (c++, ...) actually already treat throw as an expression. Some (kotlin, ...) even leave out statements completely and treat everything as an expression.



Others (c#, php, ...) provide workarounds like the ?? null-concealing or ?. elvis operator to solve this very use case.



Maybe in the future we get one of those features into the ecmascript standard (there is even an open proposal to include this) until then your best bet is to use a function like:



function assertPresent(value, message)
{
if(!value) {
throw new Error(message);
} else {
return value;
}
}





share|improve this answer















Your problem is that an assignment expects an expression but you give it a statement



The Syntax for initializing/assigning a variable is:



var|let|const <variableName> = <expression>


but you use



var|let|const <variableName> = <statement>


which is invalid Syntax.



Expressions



An expression is something that produces a value.



What is a "value"?



A value is anything that is a type in Javascript




  • Numbers

  • Strings

  • Booleans

  • Objects

  • Arrays

  • Symbols


Examples for Expressions:



Literals



var x = 5;


x is assigned the value "5"



A function call



var x = myFunc();


myFunc() produces a value that is assigned to x



The produced value of a function is its return value - A function always returns, and if it doesn't explicitly, it returns undefined.



Functions have the added benefit of being able to contain statements in their body - Which will be the solution to your question - But more on that later.



Statements



A statement is something that performs an action. For Example:



A loop



for (var i = 0; i < 10; i++) { /* loop body */ }


This loop performs the action of executing the loop body 10 times



Throwing an error



throw new Error()


Unwinds the stack and stops the execution of the current frame



So why can't we mix both?



When you want to assign to a variable, you want an expression because you want the variable to have a value.



If you think about it, it should be clear that it will never work with a statement. Giving a variable an "action" is nonsense. What is that even supposed to mean?



Therefore you cannot use the throw statement since it does not produce a value.



You can only have one or the other.
Either you are (expression) something or you do (statement) something.



A fix



You can convert any statement into an expression by wrapping it in a function, I suggest using an IIFE (Immediately invoked function expression) - basically a function that invokes itself - to do just that



var x = 5 || (() => throw new Error())()


This works because the right side is now a function and a function is an expression which produces a value.



Future Possibilities



Technically there is nothing that prevents this from working.



Many languages (c++, ...) actually already treat throw as an expression. Some (kotlin, ...) even leave out statements completely and treat everything as an expression.



Others (c#, php, ...) provide workarounds like the ?? null-concealing or ?. elvis operator to solve this very use case.



Maybe in the future we get one of those features into the ecmascript standard (there is even an open proposal to include this) until then your best bet is to use a function like:



function assertPresent(value, message)
{
if(!value) {
throw new Error(message);
} else {
return value;
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 19 at 5:44









eFarzad

604922




604922










answered Feb 11 at 8:06









Patrick HollweckPatrick Hollweck

1,2701119




1,2701119








  • 5





    As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

    – TheHansinator
    Feb 11 at 13:54











  • Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

    – jcaron
    Feb 11 at 17:37






  • 1





    It's also an expression (of type void) in C++.

    – The Vee
    Feb 11 at 18:13














  • 5





    As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

    – TheHansinator
    Feb 11 at 13:54











  • Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

    – jcaron
    Feb 11 at 17:37






  • 1





    It's also an expression (of type void) in C++.

    – The Vee
    Feb 11 at 18:13








5




5





As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

– TheHansinator
Feb 11 at 13:54





As an aside, C# 6 allowed "throw" to be an expression precisely to enable scenarios like this - the return type of the expression was inferred from context. I imagine that something like this would be even easier to conceptually add to JavaScript, since it doesn't check return types at compile time.

– TheHansinator
Feb 11 at 13:54













Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

– jcaron
Feb 11 at 17:37





Nitpicking, it's the || operator which is expecting two expressions here, not the assignment.

– jcaron
Feb 11 at 17:37




1




1





It's also an expression (of type void) in C++.

– The Vee
Feb 11 at 18:13





It's also an expression (of type void) in C++.

– The Vee
Feb 11 at 18:13











19














You could move the throwing of the exception into a function, because throw is a statement of control flow, and not an expression:




An expression is any valid unit of code that resolves to a value.







const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');








share|improve this answer





















  • 7





    Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

    – Dan Robertson
    Feb 11 at 10:09






  • 1





    Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

    – T.J. Crowder
    Feb 12 at 10:14


















19














You could move the throwing of the exception into a function, because throw is a statement of control flow, and not an expression:




An expression is any valid unit of code that resolves to a value.







const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');








share|improve this answer





















  • 7





    Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

    – Dan Robertson
    Feb 11 at 10:09






  • 1





    Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

    – T.J. Crowder
    Feb 12 at 10:14
















19












19








19







You could move the throwing of the exception into a function, because throw is a statement of control flow, and not an expression:




An expression is any valid unit of code that resolves to a value.







const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');








share|improve this answer















You could move the throwing of the exception into a function, because throw is a statement of control flow, and not an expression:




An expression is any valid unit of code that resolves to a value.







const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');








const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');





const throwError = function (e) { throw new Error(e); };

var un = undefined,
v3 = un || throwError('un is not set!');






share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 11 at 10:16

























answered Feb 11 at 7:56









Nina ScholzNina Scholz

198k15110180




198k15110180








  • 7





    Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

    – Dan Robertson
    Feb 11 at 10:09






  • 1





    Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

    – T.J. Crowder
    Feb 12 at 10:14
















  • 7





    Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

    – Dan Robertson
    Feb 11 at 10:09






  • 1





    Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

    – T.J. Crowder
    Feb 12 at 10:14










7




7





Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

– Dan Robertson
Feb 11 at 10:09





Why not just have const throwf = function(err) { throw err } and then it can be used anywhere.

– Dan Robertson
Feb 11 at 10:09




1




1





Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

– T.J. Crowder
Feb 12 at 10:14







Of note: throw expressions are at Stage 2 of the process for being added to the language. :-) Until/unless that happens, a function wrapper like the (updated) one above is the simple workaround.

– T.J. Crowder
Feb 12 at 10:14













3














As other answers have stated, it is because throw is a statement, which can't be used in contexts which expect expressions, such as on the right side of a ||. As stated by others, you can get around that by wrapping the exception in a function and immediately calling it, but I'm going to make the case that doing so is a bad idea because it makes your intent less clear. Three extra lines of code is not a big deal for making the intent of your code very clear and explicit. I personally think that throw being statement-only is a good thing because it encourages writing more straightforward code that is less likely to cause other developers to scratch their heads when encountering your code.



The || defaulting idiom is useful when you want to provide default or alternative values for undefined, null, and other falsy values, but I think it loses a lot of its clarity when used in a branching sense. By "branching sense", I mean that if your intent is to do something if a condition holds (the doing something in this case being throwing an exception), then condition || do_something() is really not a clear way to express that intent even though it is functionally identical to if (!condition) {do_something()}. Short-circuit evaluation isn't immediately obvious to every developer and || defaulting is only understood because it's a commonly-used idiom in Javascript.



My general rule of thumb is that if a function has side effects (and yes, exceptions count as side effects, especially since they're basically non-local goto statements), you should use an if statement for its condition rather than || or &&. You're not golfing.



Bottom line: which is going to cause less confusion?



return value || (() => {throw new Error('an error occurred')})()


or



if (!value) {
throw new Error('an error occurred')
}
return value


It's usually worth it to sacrifice terseness for clarity.






share|improve this answer



















  • 1





    An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

    – ttulka
    Feb 12 at 6:55






  • 1





    @ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

    – Beefster
    Feb 12 at 7:57






  • 1





    And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

    – Beefster
    Feb 12 at 8:04






  • 1





    I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

    – ttulka
    Feb 12 at 8:46






  • 1





    An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

    – Beefster
    Feb 12 at 8:51
















3














As other answers have stated, it is because throw is a statement, which can't be used in contexts which expect expressions, such as on the right side of a ||. As stated by others, you can get around that by wrapping the exception in a function and immediately calling it, but I'm going to make the case that doing so is a bad idea because it makes your intent less clear. Three extra lines of code is not a big deal for making the intent of your code very clear and explicit. I personally think that throw being statement-only is a good thing because it encourages writing more straightforward code that is less likely to cause other developers to scratch their heads when encountering your code.



The || defaulting idiom is useful when you want to provide default or alternative values for undefined, null, and other falsy values, but I think it loses a lot of its clarity when used in a branching sense. By "branching sense", I mean that if your intent is to do something if a condition holds (the doing something in this case being throwing an exception), then condition || do_something() is really not a clear way to express that intent even though it is functionally identical to if (!condition) {do_something()}. Short-circuit evaluation isn't immediately obvious to every developer and || defaulting is only understood because it's a commonly-used idiom in Javascript.



My general rule of thumb is that if a function has side effects (and yes, exceptions count as side effects, especially since they're basically non-local goto statements), you should use an if statement for its condition rather than || or &&. You're not golfing.



Bottom line: which is going to cause less confusion?



return value || (() => {throw new Error('an error occurred')})()


or



if (!value) {
throw new Error('an error occurred')
}
return value


It's usually worth it to sacrifice terseness for clarity.






share|improve this answer



















  • 1





    An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

    – ttulka
    Feb 12 at 6:55






  • 1





    @ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

    – Beefster
    Feb 12 at 7:57






  • 1





    And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

    – Beefster
    Feb 12 at 8:04






  • 1





    I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

    – ttulka
    Feb 12 at 8:46






  • 1





    An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

    – Beefster
    Feb 12 at 8:51














3












3








3







As other answers have stated, it is because throw is a statement, which can't be used in contexts which expect expressions, such as on the right side of a ||. As stated by others, you can get around that by wrapping the exception in a function and immediately calling it, but I'm going to make the case that doing so is a bad idea because it makes your intent less clear. Three extra lines of code is not a big deal for making the intent of your code very clear and explicit. I personally think that throw being statement-only is a good thing because it encourages writing more straightforward code that is less likely to cause other developers to scratch their heads when encountering your code.



The || defaulting idiom is useful when you want to provide default or alternative values for undefined, null, and other falsy values, but I think it loses a lot of its clarity when used in a branching sense. By "branching sense", I mean that if your intent is to do something if a condition holds (the doing something in this case being throwing an exception), then condition || do_something() is really not a clear way to express that intent even though it is functionally identical to if (!condition) {do_something()}. Short-circuit evaluation isn't immediately obvious to every developer and || defaulting is only understood because it's a commonly-used idiom in Javascript.



My general rule of thumb is that if a function has side effects (and yes, exceptions count as side effects, especially since they're basically non-local goto statements), you should use an if statement for its condition rather than || or &&. You're not golfing.



Bottom line: which is going to cause less confusion?



return value || (() => {throw new Error('an error occurred')})()


or



if (!value) {
throw new Error('an error occurred')
}
return value


It's usually worth it to sacrifice terseness for clarity.






share|improve this answer













As other answers have stated, it is because throw is a statement, which can't be used in contexts which expect expressions, such as on the right side of a ||. As stated by others, you can get around that by wrapping the exception in a function and immediately calling it, but I'm going to make the case that doing so is a bad idea because it makes your intent less clear. Three extra lines of code is not a big deal for making the intent of your code very clear and explicit. I personally think that throw being statement-only is a good thing because it encourages writing more straightforward code that is less likely to cause other developers to scratch their heads when encountering your code.



The || defaulting idiom is useful when you want to provide default or alternative values for undefined, null, and other falsy values, but I think it loses a lot of its clarity when used in a branching sense. By "branching sense", I mean that if your intent is to do something if a condition holds (the doing something in this case being throwing an exception), then condition || do_something() is really not a clear way to express that intent even though it is functionally identical to if (!condition) {do_something()}. Short-circuit evaluation isn't immediately obvious to every developer and || defaulting is only understood because it's a commonly-used idiom in Javascript.



My general rule of thumb is that if a function has side effects (and yes, exceptions count as side effects, especially since they're basically non-local goto statements), you should use an if statement for its condition rather than || or &&. You're not golfing.



Bottom line: which is going to cause less confusion?



return value || (() => {throw new Error('an error occurred')})()


or



if (!value) {
throw new Error('an error occurred')
}
return value


It's usually worth it to sacrifice terseness for clarity.







share|improve this answer












share|improve this answer



share|improve this answer










answered Feb 12 at 0:38









BeefsterBeefster

429411




429411








  • 1





    An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

    – ttulka
    Feb 12 at 6:55






  • 1





    @ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

    – Beefster
    Feb 12 at 7:57






  • 1





    And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

    – Beefster
    Feb 12 at 8:04






  • 1





    I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

    – ttulka
    Feb 12 at 8:46






  • 1





    An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

    – Beefster
    Feb 12 at 8:51














  • 1





    An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

    – ttulka
    Feb 12 at 6:55






  • 1





    @ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

    – Beefster
    Feb 12 at 7:57






  • 1





    And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

    – Beefster
    Feb 12 at 8:04






  • 1





    I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

    – ttulka
    Feb 12 at 8:46






  • 1





    An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

    – Beefster
    Feb 12 at 8:51








1




1





An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

– ttulka
Feb 12 at 6:55





An exception is a side effect indeed, but - if not used for flow control - it's just an exception (can lead to a system crash, and that's fine), not a flow control. Using if statement attracts the eye of the reader and mentally makes from an exception to a flow control, which is wrong, because exceptions should not be used in that manner. Written as I proposed makes an exception to an assertion, which is better (could be easily ignored by the reader). But maybe the best would be not to use such checks at all and let the runtime itself deal with wrong parameters...

– ttulka
Feb 12 at 6:55




1




1





@ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

– Beefster
Feb 12 at 7:57





@ttulka If your intent is to have an assertion, you would be far better off having an assert function defined somewhere that wraps this intention. Something like function assert(value, message) { if (value) {return value} else {throw new Error(message || 'assertion failed')}} will do just fine. Or you could use an assertion library. You can even remove the assertion for release builds with assert = () => {}

– Beefster
Feb 12 at 7:57




1




1





And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

– Beefster
Feb 12 at 8:04





And even if an exception isn't used for flow control, it still effectively acts as a goto somewhere with catch statements effectively being comefroms. Now this can be reasonable in many cases, especially when in JS they're used more like panics and caught at the top of some sort of dispatcher, but exceptions can often lead to surprises when not caught at the API boundaries.

– Beefster
Feb 12 at 8:04




1




1





I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

– ttulka
Feb 12 at 8:46





I don't think it is same. If I don't do the explicit check, an exception will be thrown anyway, I just want to "customize" it. The idea with assert is okay, but it's not different from proposals in other answers. My motivation is to use language constructs directly without any boilerplate code.

– ttulka
Feb 12 at 8:46




1




1





An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

– Beefster
Feb 12 at 8:51





An if statement isn't boilerplate. You don't even have to include the braces if all you're doing is throwing an exception. Then you can keep it on the same line.

– Beefster
Feb 12 at 8:51











1














Like others have said the problem is that throw is a statement and not an expression.



There is however really no need for this dichotomy. There are languages where everything is an expression (no statements) and they're not "inferior" because of this; it simplifies both syntax and semantic (e.g. you don't need separate if statements and the ternary operator ?:).



Actually this is just one of the many reasons for which Javascript (the language) kind of sucks, despite Javascript (the runtime environment) being amazing.



A simple work-around (that can be used also in other languages with a similar limitation like Python) is:



function error(x) { throw Error(x); }


then you can simply write



let x = y.parent || error("No parent");


There is some complexity in having throw as an expression for statically typed languages: what should be the static type of x() ? y() : throw(z)?; for example C++ has a very special rule for handling a throw expression in the ternary operator (the type is taken from the other branch, even if formally throw x is considered an expression of type void).






share|improve this answer





















  • 2





    Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

    – Cristik
    Feb 14 at 0:30
















1














Like others have said the problem is that throw is a statement and not an expression.



There is however really no need for this dichotomy. There are languages where everything is an expression (no statements) and they're not "inferior" because of this; it simplifies both syntax and semantic (e.g. you don't need separate if statements and the ternary operator ?:).



Actually this is just one of the many reasons for which Javascript (the language) kind of sucks, despite Javascript (the runtime environment) being amazing.



A simple work-around (that can be used also in other languages with a similar limitation like Python) is:



function error(x) { throw Error(x); }


then you can simply write



let x = y.parent || error("No parent");


There is some complexity in having throw as an expression for statically typed languages: what should be the static type of x() ? y() : throw(z)?; for example C++ has a very special rule for handling a throw expression in the ternary operator (the type is taken from the other branch, even if formally throw x is considered an expression of type void).






share|improve this answer





















  • 2





    Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

    – Cristik
    Feb 14 at 0:30














1












1








1







Like others have said the problem is that throw is a statement and not an expression.



There is however really no need for this dichotomy. There are languages where everything is an expression (no statements) and they're not "inferior" because of this; it simplifies both syntax and semantic (e.g. you don't need separate if statements and the ternary operator ?:).



Actually this is just one of the many reasons for which Javascript (the language) kind of sucks, despite Javascript (the runtime environment) being amazing.



A simple work-around (that can be used also in other languages with a similar limitation like Python) is:



function error(x) { throw Error(x); }


then you can simply write



let x = y.parent || error("No parent");


There is some complexity in having throw as an expression for statically typed languages: what should be the static type of x() ? y() : throw(z)?; for example C++ has a very special rule for handling a throw expression in the ternary operator (the type is taken from the other branch, even if formally throw x is considered an expression of type void).






share|improve this answer















Like others have said the problem is that throw is a statement and not an expression.



There is however really no need for this dichotomy. There are languages where everything is an expression (no statements) and they're not "inferior" because of this; it simplifies both syntax and semantic (e.g. you don't need separate if statements and the ternary operator ?:).



Actually this is just one of the many reasons for which Javascript (the language) kind of sucks, despite Javascript (the runtime environment) being amazing.



A simple work-around (that can be used also in other languages with a similar limitation like Python) is:



function error(x) { throw Error(x); }


then you can simply write



let x = y.parent || error("No parent");


There is some complexity in having throw as an expression for statically typed languages: what should be the static type of x() ? y() : throw(z)?; for example C++ has a very special rule for handling a throw expression in the ternary operator (the type is taken from the other branch, even if formally throw x is considered an expression of type void).







share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 13 at 17:35

























answered Feb 13 at 9:16









65026502

87.9k13115218




87.9k13115218








  • 2





    Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

    – Cristik
    Feb 14 at 0:30














  • 2





    Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

    – Cristik
    Feb 14 at 0:30








2




2





Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

– Cristik
Feb 14 at 0:30





Just a note that your work-around was already provided in stackoverflow.com/a/54626116/1974224.

– Cristik
Feb 14 at 0:30


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54626074%2fwhy-doesnt-logical-or-work-with-error-throwing-in-javascript%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Human spaceflight

Can not write log (Is /dev/pts mounted?) - openpty in Ubuntu-on-Windows?

張江高科駅