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-guideeslinteslint-config-nexteslint-config-prettiereslint-config-turboeslint-import-resolver-typescripteslint-plugin-importeslint-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
ornpcPair
-
PascalCase
for classes -
SCREAMING_CASE
for global constants -
Use
const
by default. Uselet
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 stringThis 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) {...}// NOTfunction something(my_arg){...} -
else
andelse 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 {...}// NOTif (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.