Skip to content

Instantly share code, notes, and snippets.

@ngocdevnull
Forked from nghiamx49/code-style.md
Last active January 15, 2025 09:24
Show Gist options
  • Save ngocdevnull/a55849894a60f9fedf9a421760630733 to your computer and use it in GitHub Desktop.
Save ngocdevnull/a55849894a60f9fedf9a421760630733 to your computer and use it in GitHub Desktop.

Angular Team - Code Style Guidance

  • Adhere to English rules (grammar, spelling,...)

  • Variable name must be self-explanatory and describe the stored value.

  • Variable name must be nouns.

  • Function name must be verbs.

  • Using camelCase for identifier names (for both variable and function)

  • Always use the lowercase version with primitive types string, boolean, and number instead of String, Boolean, and Number

  • Interface must be end with Model.

interface User { 
   firstName: string; 
   lastName: string; 
} 

must be

interface UserModel { 
    firstName: string; 
    lastName: string; 
} 
  • Use UpperCamelCase for module-level constants and enum values, and lowerCamelCase for constants or variables instantiated multiple times.
// Module-level constant

const PageSizes = [0,5,10]

// Constants or variables that can be instantiated multiple times

const pageSizes = [0,5,10]
  • Prefer interfaces over type literal aliases when defining the shape of objects
// Using an interface

interface User { 
   firstName: string; 
   lastName: string; 
} 

// Using a type alias (not recommended for objects) 

type User = { firstName: string; lastName: string; }
  • Prefer using the ternary operator (? :) over if-else for concise conditional expressions.

  • Private variables must have # prefix from the ES2022.

However, while ES2021 or less, TS will use WeakMap in place of # so using TS private and _ prefix combination instead.


// Latest ES (from 2022)

readonly #fixedHeight = 10;

#userName: string;

// ES2021 or less

private readonly _fixedHeight = 10;

private _userName: string;

  • Boolean variables must begin with has/is. For example:

public isLoaded = false;

public hasInnerText = true;

  • Variable with type Map, Set must end with Map, Set respectively. For example:

public readonly locationMap = new Map([]);

public readonly uniqueDataSet = new Set([]);

  • Variable with Array type must be in plural form. For Example:

public readonly locations: string[] = [];

  • Variables without initial value must have pre-defined type. For example:

public isLoaded: boolean;

public locations: string[];

public locationMap: Map;

  • Avoid to using any as variable type. If there is an unknown property of interface or type, use unkown instead.

If the unknown type is an object, Record type must be used instead of Object type.

  • For empty object, do not use {} symbol, using Recond<string, never> instead.

  • Don't use function in template.

  • Use effect less, try signals in computed.

  • Observable and Subject must end with $ suffix.


public users$: Observable<User[]>;

  • Subject should be private readonly and they should expose via asObservable() if needed:

readonly #sampleSuject$ = new Subject<void>();

public sampleSubject$ = this.#sampleSuject$.asObservable();

  • When Subscribe a stream, passed an Observer is recommended:

this.sampleSubject$.subscribe({

next: () => { // do somthing },

error: () => { // do somthing },

complete: () => { // do somthing }

})

  • Using noop for empty callback.

import { noop } from 'rxjs';

navigator.clipboard.writeText('Writing Data').then(noop);

  • Prefer to use Standalone component over NgModule.

  • Prefer to use signal input, output and model instead of @Input and @Output decorator.

  • All class methods and functions must have return type:

  • Variables ordering must follow the rule:

  • Private readonly variables

  • Private variables

  • protected readonly variables

  • protected variables

  • Public readonly variables

  • Public variables

  • Class methods ordering must follow the rule:

  • Constructor

  • Angular component lifecycle methods

  • ngOnChanges

  • ngOnInit

  • ngDoCheck

  • ngAfterViewInit

  • ngAfterViewChecked

  • ngAfterContentInit

  • ngAfterContentChecked

  • Public methods

  • Private methods

  • Protected methods


@Component({

standalone: true,

selector: 'example',

templateUrl: './example.component.html',

styleUrl './example.component.scss',

changeDetection: ChangeDetectionStrategy.OnPush,

})

export class Example implements OnChanges, OnInit {

readonly #innerIsLoaded$ = new BehaviorSubject<boolean>(false);

readonly #salaryRange = 1000;

@ViewChild(SomeService) #someService: SomeService;

@ViewChildren(SomeService) #someServices: QueryList<SomeService>;

#isDirector: boolean;

protected readonly salaryFormName = 'Salary Form';

protected hasMarker: boolean;

public readonly isLoaded$: Observable<boolean> = this.innerIsLoaded$.asObservable();

public readonly formGroup = new FormGroup({});

public assignedColor: Color;

set positionName(value: string) {

// Implementation here

}

get positionName(): string {

// Implementation here

}

@Input() public hasBorder = false;

@Output() public positionChanged = new EventEmitter();

@HostBinding('class.dark')

public isDarkTheme = true;

public constructor() {}

public ngOnChanges(): void {

// Do something

this.doSomethingElse();

}

public ngOnInit(): void {

// Implementation here

this.doSomething()

}

@HostListener('click', '$event.target')

public hideInput(element: HTMLElement): void {

// Implementation here

}

  

public changePosition(): void {

// Do something

this.fireSomeone();

}

public fireSomeone(): void {

// Implementation here

}

private doSomething(): void {

// Implementation here

}

private doSomethingElse(): void {

// Implementation here

}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment