Skip to content

Code Style

7sempra edited this page Mar 8, 2021 · 11 revisions

All code checked in to the roster must conform to the code style guide. Please make sure this is true before you send it for review to save everyone time.

Core

In general, we use the Google Javascript Style Guide, with the following reiterations / additions.

Highlights

  • Indent with spaces, not tabs
  • 2 spaces per indent
  • 80 characters per line
  • Use single quote, ', or backtick ` for string literals, not double-quote, ".
  • K&R-style brackets:
    // Yes
    function foo() {
      // ...
    }
    
    // No
    function foo()
    {
      // ...
    }
  • Two indents (i.e. 4 spaces) when breaking a line. Break lines at highest syntactic level possible.
    const foo =
        reallyLongObjectName.doReallyLongMethod(
            param1, param2, param3);
  • A single space between control flow keywords (if, when, else) and surrounding brackets or parens:
    // Yes
    if (foo) {
      // ...
    } else {
      // ...
    }
    
    // No
    if(foo){
    if ( foo ) {
    if( foo ){
  • Spaces on both sides of arithmetic operators
    // Yes
    let foo = a + b / 3;
    
    // No
    let foo = a+b/3;
  • Do not wrap parameter or argument lists:
    // Yes
    longFunctionCall(
            longVariableName1,
            longVariableName2,
            longVariableName3,
            longVariableName4);
    
    // Yes (but prefer above)
    longFunctionCallNameWithShortArgs(
            foo, bar, baz);
    
    // No
    longFunctionCall(longVariableName1, longVariableName2,
            longVariableName3, longVariableName4);

Typescript-specific

  • Type annotations are of the form symbol: type.
    // Yes
    const foo: Bar;
    
    // No
    const foo:Bar;
    const foo : Bar;
    const foo :Bar;
  • Type union or intersection operators have spaces on both sides:
    // Yes
    const foo: Bar | undefined;
    
    // No
    const foo: Bar|undefined;
  • Functions whose arguments/return type cannot fit on one line should put one parameter on each line, with the closing brace/return type on its own line as well. Use trailing commas for the parameter list.
    function veryLongFunctionHeader(
        param1: type1,
        param2: type2,
        param3: type3,
        param4: type4,
    ): number | undefined  {
      // ...
    }
  • Do not use default exports. Always name exports, even if there is only one export (in which case the name of the export should match the file name). Routes are an exception to this rule.
    // In file fixTheBalloons.ts
    
    // Yes
    export function fixTheBalloons() {
    }
    
    // No
    export default function fixTheBalloons() {
    }

Misc

  • Prefer async/await over chained Promise calls. This is not a hard-and-fast rule; some things are more elegant with a chain.

    // Preferred
    async function fetchStuff() {
      const firstThing = await getFirstThing();
      let secondThing: ThingReturnType | null = null;
      try {
        secondThing = await getSecondThing();
      } catch (err) {
        // Do something with err
      }
      return processStuff(firstThing, secondThing);
    }
    
    // Not preferred
    function fetchStuff() {
      let firstThing: FirstThing | null = null;
    
      return Promise.resolve()
      .then(() => {
        return getFirstThing();
      })
      .then(_firstThing => {
        firstThing = _firstThing;
        return getSecondThing();
      })
      .catch(err => {
        // Handle err
      })
      .then(secondThing => {
        return processStuff(firstThing, secondThing);
      })
    }
  • When using chained promise calls, do not indent chained .then() and .catch() calls

    return Promise.resolve()
    .then(() => {
      console.log('First step');
    })
    .catch(e => {
      console.error(e.message);
    });
  • When using Promises, always use the native Promise type, not a Promise extension like Bluebird.