Skip to content

Latest commit

 

History

History
104 lines (91 loc) · 4.54 KB

style-guide.ts.md

File metadata and controls

104 lines (91 loc) · 4.54 KB

TypeScript Style Guide

Last updated on 2024-11-18.

This document contains guidelines for Angular TypeScript files.

Do

Must do

  • use Angular coding style guide
  • use Prettier
    • use config from /.prettierrc.json
    • use for .ts, .html, .scss, .md, (@ToDo check .json)
    • use Prettier on save hook
  • use ESLint
    • use config from /.eslint.json (@ToDo check .json)
  • use descriptive and meaningful names for all symbols
    • boolean fields always start with is, has, show or alike (e.g. isLoading or hasChanges())
    • event functions start with on (e.g., onClick())
  • refactor symbol names if necessary (e.g., due to requirements changes)
  • annotate types for everything except implicitly deferred (e.g. const x = 1)
    • also for function parameters and return values (also void)
  • clean up debug code before committing (e.g., no console.log)
  • use private by default, to encapsulate properties and methods
  • use protected for symbols that should be accessible in the component's view template
  • use readonly by default, unless a property needs to be reassigned
    • always use readonly on properties that are initialized by Angular
  • use const by default, unless a variable needs to be reassigned
  • prefer using the AsyncPipe, use the takeUntilDestroyed() operator if subscribing manually
  • suffix observables with $
  • keep constructors and lifecycle hooks simple and clean (basically only call methods, except one-liners)

Should do

  • keep components and directives focused on presentation
  • max. 400 LoC per file (e. g. extract static functions to utils)
  • prefer types to interfaces
  • prefer types to enums
  • group components, directives, pipes & services like this
    • decorator (@Component)
    • class with extends & implements
    • properties
    • injects (inject())
    • methods
      • static
      • constructor
      • lifecycle hooks
      • control value accessor
      • host handler
      • other methods
  • place fields and methods next to each other if they belong together
    • no alphabetic order, no order by access modifier
  • try to avoid nested RxJS subscriptions (e.g., use switchMap instead)
  • prefer easily understandable code over performance (except for performance-critical code)
  • prefer short functions (no spaghetti code)
  • use comments for complex code, and only if necessary (the usage of descriptive and meaningful names for methods and variables should be enough in many cases)
  • mark todos with // @ToDo: task description
  • distinguish between Smart/Controller and Dumb/Presentational Components
  • use LazyLoading for components
  • immutablility over mutability (for OnPush and OnChanges)
    • use ... spread operator for shallow copies
    • use structeredClone() for deep copies
  • prefer ChangeDetectionStrategy.OnPush
  • prefer Standalone Components over Modules
  • prefer default ViewEncapsulation (Emulated)
  • prefer inject() over constructor dependency injection
    • group all inject() calls at the top of the constructor
  • prefer initial / default values over :Type | undefined
  • prefer ?: Type shorthand over :Type | undefined
  • use ! with caution and only if you are sure that the value can never be null or undefined (e.g. required @Inputs, static @ViewChild)
  • use { required: true } for required @Inputs
  • use @HostBinding and @HostListener instead of plain JS listeners
    • @ToDo check if host decorator should be mentioned here
  • use variable as Type for type castings instead of <Type>variable

Don't

  • don't use (default) public modifier for properties and methods
  • don't use ambiguous or unfamiliar abbreviations
  • don't leave debug logs in the codebase
  • remove empty constructors
  • remove empty methods
  • try to avoid inline templates (except one-liners)
  • try to avoid any, prefer unknown
  • try to avoid (if possible) these lifecycle hooks
    • DoCheck()
    • AfterContentChecked()
    • AfterViewChecked()
  • don't put leading I for interfaces

Resources

Back to index