Skip to content

TypeScript

Again, please in most cases use TypeScript over JavaScript.

Overview

This should mostly be done by prettier and eslint, but so you know

  • Try to prioritise readability of code

  • 2 spaces as tabs

  • Lines should not be longer than 80 characters (install extension)

  • Trailing commas when the bracket on a new line

  • NO trailing whitespaces! (Install an extension to remove it for you)

  • Space after comments e.g. // something

  • Order imports alphabetically

  • Prefer documentation over comments (see below on how you do that)

  • Comments should only be written when necessary, mainly to describe why something is done the way it is or to example a really unreadable bit of code (however this normally means you should change the code).

  • Methods should be ordered alphabetically (with private methods ordered separately and at the bottom of the file)

    export function aFunc() {}
    export function bFunc() {}
    export function zFunc() {}
    function aPrivateFunc() {}
    function bPrivateFunc() {}

These are really strict, if you take anything away remember this:

  • Use a formatter and linter: styling should be consistent throughout the project
  • Readability of code takes precedent

Use a Linter

Linters usually will catch most issues, these can be installed as extensions to your preferred editor. E.g. for TypeScript we will be using ESLint

Example ESLint config (.estlintrc.cjs) which supports, react and typescript:

const fs = require("node:fs");
const path = require("node:path");
const project = path.resolve(process.cwd(), "tsconfig.json");
const resolvedExtends = [
"@vercel/style-guide/eslint/node",
"@vercel/style-guide/eslint/typescript",
"@vercel/style-guide/eslint/browser",
"@vercel/style-guide/eslint/react",
"eslint-config-turbo",
].map(require.resolve);
module.exports = {
env: {
es2022: true,
},
extends: [...resolvedExtends, "plugin:prettier/recommended"],
ignorePatterns: ["node_modules/", "dist/", "build/"],
plugins: [],
parserOptions: {
project,
ecmaVersion: "latest",
sourceType: "module",
},
rules: {
"import/no-default-export": "off",
"no-console": "off",
"react/react-in-jsx-scope": [0],
"react/self-closing-comp": [
"error",
{
component: true,
html: true,
},
],
"turbo/no-undeclared-env-vars": "off",
"unicorn/filename-case": [
"error",
{
cases: {
snakeCase: true,
pascalCase: true,
},
ignore: ["vite-env.d.ts"],
},
],
"@typescript-eslint/explicit-function-return-type": [0],
},
settings: {
"import/resolver": {
typescript: {
project,
},
},
"import/parser": {
"@typescript-eslint/parser": [".ts", ".tsx"],
},
},
};

Node that you must add the following dependencies:

@vercel/style-guide
eslint
eslint-config-next
eslint-config-prettier
eslint-config-turbo
eslint-import-resolver-typescript
eslint-plugin-import
eslint-plugin-prettier

For formatters, we recommend prettier with the following config:

{
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"printWidth": 80,
"useTabs": false
}

(you will need to add prettier as a dependency).

You can then add the following to your package.json:

{
// ...
"scripts": {
// ...
"lint": "eslint src --ext ts,tsx,mjs,js,jsx,mdx --report-unused-disable-directives",
"lint:fix": "eslint src --ext ts,tsx,mjs,js,jsx --report-unused-disable-directives --fix",
"format": "prettier --write 'src/**/*.tsx' 'src/**/*.ts' '**/*.json' .prettierrc .eslintrc"
}
// ...
}

Specifically

These are normally the typical styling recommendations for JavaScript:

  • camelCase for variables + functions. Preferably, if you had an acronym in the name, all letters should be the same case e.g. myNPC or npcPair

  • PascalCase for classes

  • SCREAMING_CASE for global constants

  • Use const by default. Use let only if you need to reassign to the variable.

    Constants in JavaScript + TypeScript are not actually constant, they just can’t be reassigned.

  • Reduce use of any. Unfortunately TypeScript can be quite dumb at times so this can be used for type conversion.

  • Prefer " over ' for strings, unless you have " inside the string

    This one is more personal so not necessary (consistency though!)

  • Starting a new scope with { should be on the same line, not on a new line, e.g. in javascript:

    function something(my_arg) {
    ...
    }
    // NOT
    function something(my_arg)
    {
    ...
    }
  • else and else if statements should be on the same line as the scope (ignore the lecturers’ preferences for this).

    if (myVar === 'Something') {
    ...
    } else if (myOtherVar !== 'THING') {
    ...
    } else {
    ...
    }
    // NOT
    if (myVar === 'Something') {
    ...
    }
    else if (myOtherVar !== 'THING') {
    ...
    }
    else {
    ...
    }
  • Prefer creating your own interface over using the object keyword

  • ESLint basically covers all my other issues

Documentation

TypeScript and JavaScript have actually good documentation (probably the only good thing about them), so please use it.

Basically please read through this.