When is it appropriate to use a semicolon?
I know that JavaScript (and thus TypeScript) support the omission of semicolons in many cases. Nevertheless I want to add semicolons to be unambiguous as suggested in TypeScript Deep Dive
However I cannot find a guide that lists where to use semicolon. For example look at the following code
class Person {
private name: string; // A
constructor(name: string) {
this.name = name;
}; // B
public add = () => {
return "C";
}; // C
}; // D
I'm fairly sure to use a semicolon at A. But what about B, C, D and all the other cases not covered by my example?
I'm not asking where to omit semicolon but where to add them. An answer like always does not fulfill my needs since I cannot add a ;
after public
. I want to know where exactly to put semicolon.
Just prefix lines starting with [
, (
, or ` with a semicolon and you're (almost) golden*
Using the same example as another answer:
var x = { xx : "hello", yy : "world"}
(function () {
console.log("Hello World");
})();
We add a semicolon according to this rule:
var x = { xx : "hello", yy : "world"}
;(function () {
otherwise javascript thinks we're trying to call(
some function, or reference[
some array. This is simpler, easier to follow, and it's visually easier to spot. You also need semicolons in for
loops, but the .forEach
method is a cleaner and easier method. I'd confidently say this one rule covers 99% of the scenarios you need to use a semicolon in javascript/typescript.
Following this method, it's important to associate a newline with terminating a statement.
*This returns the venerable undefined
:
return
7
After return, there's a newline, and the browser inserts a semicolon, terminating the statement like this:
return; // this will return undefined.
7
Do this instead:
return (
7
)
Javascript is actually pretty smart with semicolons, there's an open paren, so no semicolon is inserted until the closing paren is found.
If you have a habit of putting semicolons everywhere and not knowing exactly when they are needed, you could read this for a several page long explanation: http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding
I admit most people will still just litter semi colons at the end of every line, but if you're new and just learning, this is the better approach.
Like some other modern languages derived from the C syntax, JavaScript syntax was designed to allow you to omit semicolons in almost all situations. I'd say use them always or use them never*. To use them "never" the long and short of it is that every statement goes on a new line and never begin a line with (
, [
, or `
.
However, to use them "never", you should definitely be using a linter such as JavaScript Standard Style or eslint with its built-in semi
rule to disable semicolons and its no-unexpected-multiline
rule which will make sure that you avoid the few gotchas such as the following:
a = b + c
(d + e).foo()
The above is interpreted as a = b + c(d + e).foo();
Note that by following the above rule and not beginning a line with (
this situation is prevented.
Another common example is the following:
return
{
hello: "world"
};
At a glance one may think this will be interpreted as returning an object, but it actually interpreted as return;
and the code to define the object after the return statement is unreachable. Again, by following the rule of not beginning a line with {
this is avoided.
- *Okay, okay, not never, but almost never.
TL;DR: Always
Keep in mind: better safe than sorry
You should probably place them all the time. You don't need to place them in order for TypeScript to work, but you will avoid errors by doing so. ASI (Automatic Semicolon Insertion) works quite well most of time, but not always. Do you really want to run into a problem just because you didn't put a semicolon, and you keep overlooking the mistake? (Depending on your IDE, the mistake might actually be caught). But consider this perfectly valid Javascript.
var x = { xx : "hello", yy : "world"}
(function () {
console.log("Hello World");
})();
This is valid javascript (and thus valid typescript). This code will actually give an error. Uncaught TypeError: (intermediate value)(intermediate value) is not a function(…)
.
Which could be avoided by just placing a semicolon after the first line. You don't need it there, and if the next line wasn't that function line, it would probably work correctly. But you want to take that risk? It seems like taking the risk for mistakes over one extra character is not worth it to me. Plus, after a while, you just get used to place semicolons at the end of a line anyway;
Think of your colleagues
Another reason you might want to use them all the time is in the case of code changing. Your colleague might have to change your code - and in doing so thinks that the ASI will keep working even with his code change. Imagine that this is not the case, and that his change actually makes ASI do something wrong. Is it really worth that headache for your colleague? If he changes enough of your code and then suddenly runs into a lot of errors, he might be rather confused if he does not know the exact way in which ASI is working. You could save a potential colleague quite a bit of (unneccessary) work by just putting them everywhere.