TypeScript Maintainability Standards · TS-02
Clean, scalable codebases are crucial for long-term project success. Best practices are outlined within this document for guiding engineers to write maintainable TypeScript.
Methods do not exceed 10 statements · TS-02.1 · MUST
A TypeScript reflection of CS-01.1
Methods that require more than 10 statements are doing too much, engineers must make conscious, critical analysis of their work and provide methods with clear names.
Do not duplicate code · TS-02.2 · MUST
If the same statement, or statement group, appears multiple times in the codebase. Then, the responsibility of this logic should belong to one abstraction which is used in both places.
This rule enforces the DRY principle
Nested control statements do not exceed a depth of 2 · TS-02.3 · MUST
Methods which contain control statements (such as if, while, for) must only have up to 2 of such statements nested before abstracting the nested control statements into private methods.
Excessive nesting results in unmaintainable code which takes time to understand. Engineers must abstract each stage of the nested statements into a understandable methods.
Do not allow methods with more than 4 parameters · TS-02.4 · MUST
A TypeScript reflection of CS-01.21
Reduce method complexity by ensuring methods do not have more than 4 parameters. Use objects or data structures to encapsulate multiple parameters if necessary.
Do not use magic numbers or strings · TS-02.5 · MUST
Magic numbers and strings present maintainability issues and must be avoided at all times.
Use Enums over fixed sets of constants · TS-02.6 · MUST
Enums over fixed sets of constants · TS-02.6 · MUSTWhen a fixed set of constants is used for logic, these should be grouped into an Enum. This aides readibilty by giving names and groupings to magic numbers and strings.
Allow gaps between numeric values for enums · TS-02.7 · MUST
A TypeScript reflection of CS-01.27
Allow future extensions or specific business requirements by leaving gaps between the numeric values of an enum, e.g. [0, 100, 200].
Don't comment out code · TS-02.8 · MUST
A TypeScript reflection of CS-01.26
To maintain cleanliness, any code that the compiler cannot reach should never be checked-in.
Target specific versions or version ranges in package.json · TS-02.9 · MUST
package.json · TS-02.9 · MUSTNever use ”*” or ”^” for the target version of an imported package. This kind of usage can result in unexpected behaviour or the unintentional introduction of breaking changes.
Implement error logging for observability of problems · TS-02.10 · MUST
Integrate a logging tool to track and diagnose runtime errors in development and production. This can be achieved with an error handling middleware.
Error logging tool such as Sentry or Winston can be implemented to capture errors on the front end.
Enable strictNullChecks for Type safety · TS-02.12 · SHOULD
strictNullChecks for Type safety · TS-02.12 · SHOULDType null safety should be enforced on TS projects, making full use of TypeScript’s benefits that reduce runtime errors and aide readibility. Engineers should be made to explciity state if a value might be null or undefined.
Optimise imports · TS-02.13 · SHOULD
Optimising imports is important for the scalability of an application. As applications grow and file paths become longer as a result, it’s important that we keep these maintainable and readable.
Use relative imports · TS-02.14 · SHOULD
Dependency management and module portability should be optimised through the use of relative paths.
Relative import example (✅)
import { MyComponent } from './components/MyComponent';
import { Utils } from '../utils/Utils';Absolute import example (❌)
import { MyComponent } from 'project-name/src/components/MyComponent';
import { Utils } from 'project-name/src/utils/Utils';Configure aliases for improved readability · TS-02.15 · SHOULD
Aliases can be configured in tsconfig.json or in webpack to optimise imports into groups.
tsconfig.json alias example (✅)
"compilerOptions": {
"paths": {
"@components/*": ["src/components/*"],
}
}Usage
import { MyComponent } from '@components/MyComponent';