TypeScript: Difference between revisions
Translate from boss.bathcs.com |
m Pm2022 moved page BOSS/Languages/TypeScript to TypeScript |
||
| (One intermediate revision by the same user not shown) | |||
| Line 280: | Line 280: | ||
* Running package scripts, the full package name must be used e.g. <code>deno run -A npm:@biomejs/biome</code> | * Running package scripts, the full package name must be used e.g. <code>deno run -A npm:@biomejs/biome</code> | ||
* You must permit applications to use features such as environmental variables or reading your directories. If deploying yourself, it will ask for each permission. You can also permit anything by using <code>deno run -A</code> | * You must permit applications to use features such as environmental variables or reading your directories. If deploying yourself, it will ask for each permission. You can also permit anything by using <code>deno run -A</code> | ||
[[Category:Bath Open Source Society]] | |||
[[Category:Programming language guidelines]] | |||
Latest revision as of 07:03, 26 August 2026
Again, please in most cases use TypeScript over JavaScript.
Overview
This should mostly be done by biome or 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.
// somethingOrder 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 biome or ESLint.
For Biome, both formatting and linting can be configured with biome.json:
{
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"includes": ["**", "!!**/dist"]
},
"formatter": {
"enabled": true,
"indentWidth": 2,
"indentStyle": "space"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
},
"css": {
"parser": {
"tailwindDirectives": true
}
},
"overrides": [
{
"includes": ["**/*.svelte", "**/*.astro", "**/*.vue"],
"linter": {
"rules": {
"style": {
"useConst": "off",
"useImportType": "off"
},
"correctness": {
"noUnusedVariables": "off",
"noUnusedImports": "off"
}
}
}
}
]
}
Example ESLint config (.estlintrc.cjs) which supports, react and typescript:
import js from "@eslint/js";
import prettier from "eslint-plugin-prettier";
import tsParser from "@typescript-eslint/parser";
import eslintJs from "@eslint/js";
import eslintReact from "@eslint-react/eslint-plugin";
import globals from "globals";
import ts from "@typescript-eslint/eslint-plugin";
export default [
{
files: ["**/*.{ts,tsx,mjs,js,jsx}", "astro.config.mjs"],
languageOptions: {
globals: { ...globals.browser },
sourceType: "module",
ecmaVersion: 2022,
parser: tsParser,
parserOptions: {
project: ["./tsconfig.json"],
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true, // Enable JSX syntax support
},
},
},
plugins: {
eslintJs: eslintJs.configs.recommended,
eslintReact: eslintReact.configs.recommended,
prettier: prettier,
"@typescript-eslint": ts,
},
settings: {
"mdx/code-blocks": true,
},
rules: {
"@typescript-eslint/triple-slash-reference": "off",
},
},
{
...js.configs.recommended,
...ts.configs.recommendedTypeChecked,
files: ["**/*.ts", "**/*.tsx"],
rules: {
"@typescript-eslint/strict-boolean-expressions": [
2,
{
allowString: false,
allowNumber: false,
},
],
},
},
];
Node that you must add the following dependencies:
@eslint/js eslint-plugin-prettier @typescript-eslint/parser @eslint-react/eslint-plugin @typescript-eslint/eslint-plugin
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).
biome instead of prettier (even the devs behind prettier), so you may want to use that insteadYou can then add the following to your deno.jsonc:
{
"tasks": {
// Biome requires running /bin/sh which means it effectively wants all
// permissions
"biome": "deno run -A npm:@biomejs/biome",
// ...
"lint": "deno task biome lint",
"lint:fix": "deno task biome lint --write",
"format": "deno task biome check --write",
"format:check": "deno task biome check",
// With ESLINT + Prettier
"eslint": "deno run -A npm:eslint",
"prettier": "deno run -A npm:prettier",
"prettier:files": "deno task prettier 'src/**/*.{tsx,ts,md,mdx,json}' '*.{json,js,mjs,md}' '.prettierrc'",
"lint": "deno task eslint src --report-unused-disable-directives --max-warnings 0",
"lint:fix": "deno task lint --fix",
"format": "deno task prettier:files --write",
"format:check": "deno task prettier:files --check"
},
}
Specifically
These are normally the typical styling recommendations for JavaScript:
camelCasefor variables + functions. Preferably, if you had an acronym in the name, all letters should be the same case e.g.myNPCornpcPairPascalCasefor classesSCREAMING_CASEfor global constantsUse
constby default. Useletonly 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) { ... } // NOT function something(my_arg) { ... }
elseandelse ifstatements 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
objectkeywordESLint 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.
Package manager
As an asside, as already alluded to, BOSS has a standard of using deno for its package manage and runtime due to its significant focus on security. However, this comes with some learning barriers as it unlike your regular npm, yarn or bun and goes further than pnpm.
Our configuration of deno is as follows, which can be found in the deno.jsonc of any project:
{
"$schema": "https://raw.githubusercontent.com/denoland/deno/refs/tags/v2.8.0/cli/schemas/config-file.v1.json",
"tasks": {
// ... Any "scripts" from package.json
},
"minimumDependencyAge": "P2D",
"vendor": true,
"lock": { "frozen": true }
}
What this configuration does is as follows:
- When updating, the chosen dependency verion must be older than 2 days to help mitigate from supply chain attacks
- By default, the lock file is frozen, and so when adding or updating packages, you must explicity include
--frozen=false vendorfolder is used as a local cache for remote modules, decreasing overall disk usage.
Core differences with npm
- Added packages must include a namespace, e.g. anything from
npm(basically anything) should be prefixed withnpm:. You can also install from the JSR by prefixing withjsr: - Scripts are not found in
package.jsoninstead they should be in deno's config:deno.jsoncundertasks - Running "tasks" should be done through deno's task cmd:
deno task ... - Running package scripts, the full package name must be used e.g.
deno run -A npm:@biomejs/biome - You must permit applications to use features such as environmental variables or reading your directories. If deploying yourself, it will ask for each permission. You can also permit anything by using
deno run -A