This guide specifically addresses TypeScript development, focusing on idiomatic practices, patterns, and TypeScript-specific considerations.
/// admonition | type: abstract Foundational Code Standards{:target="_blank"} provide the foundation, this guide extends them for TypeScript. /// //: # (@formatter:on)
The formatting rules for TypeScript adhere to our foundational formatting standards:
- Consistent Indentation: Use 2 spaces for indentation.
- Line Length: Aim for 100 characters, but allow flexibility for readability.
- Whitespace: Use spaces around operators, after colons and semicolons, and before open braces for clarity.
- Brace Style: Use 1TBS (the one true brace style) where the opening brace is on the same line.
- Semicolons: Use semicolons at the end of statements for clarity.
/// admonition | type: info Remember, these are guidelines; adapt them for your project's needs while keeping readability in focus. ///
The naming conventions for TypeScript adhere to our foundational naming conventions with no exceptions.
- PascalCase for classes, interfaces, enums (definitions).
- camelCase for functions, variables, properties.
- Prefix booleans with
is
orhas
for clarity.
- Prefix booleans with
- UPPER_SNAKE_CASE for constants.
- lowercase package names, concatenated words (avoid underscores).
Additional Tips:
- Interfaces: Use PascalCase without an
I
prefix. - Types: Use PascalCase for type aliases and enum types.
- Members: Public members should not have an underscore prefix.
Refer to the Foundational Code Standards for general commenting and documentation guidelines. In TypeScript, use TSDoc for documenting code. Document all public APIs clearly with examples where applicable.
- Leverage Advanced Types: TypeScript offers powerful features like generics, enums, union types, and intersection types. Use these to create precise and flexible type definitions.
type Action =
| { type: 'FEED_GOAT'; payload: { goatId: string; food: string } }
| { type: 'PET_GOAT'; payload: { goatId: string } };
function handleGoatAction(action: Action) {
// Implementation
}
- Specify Types Explicitly: Minimize the use of the
any
type to maintain the benefits of TypeScript's static typing. Useunknown
if the type is genuinely uncertain and validate it.
function safelyParse(jsonString: string): unknown {
return JSON.parse(jsonString);
}
function parse(jsonString: string): any {
return JSON.parse(jsonString);
}
- Prefer Union Types Over Enums for Simplicity: While enums can be useful, consider using union types for states or categories to reduce complexity and enhance tree-shaking.
type GoatMood = 'happy' | 'hungry' | 'sleepy';
enum GoatMood {
Happy,
Hungry,
Sleepy,
}
- Optional Chaining and Nullish Coalescing: Use optional chaining (
?.
) and nullish coalescing (??
) operators to write cleaner, safer code that elegantly handles null and undefined values.
const goatName = goat?.name ?? 'Unknown Goat';
const goatName = goat && goat.name ? goat.name : 'Unknown Goat';
- Organize Code with ES Modules: Structure your project using modules to encapsulate functionality and promote reuse. Import and export types, interfaces, functions, and classes to keep the codebase organized and maintainable.
// In goat.ts
export class Goat {
constructor(public name: string) {}
}
// In main.ts
import { Goat } from './goat';
- Apply Decorators Wisely: TypeScript's experimental decorator feature can be used to annotate and modify classes and properties elegantly, especially in frameworks like Angular.
@Component({
selector: 'goat-list',
templateUrl: './goat-list.component.html',
})
export class GoatListComponent {
// Component logic
}
- Immutability and Pure Functions: Adopt functional programming principles where appropriate. Use immutable data patterns and write pure functions to improve predictability and facilitate testing.
function feedGoat(goat: Goat, food: string): Goat {
return { ...goat, lastFedWith: food };
}
function feedGoat(goat: Goat, food: string): void {
goat.lastFedWith = food;
}
Use interfaces for defining object shapes due to their extendability.
interface Goat {
name: string;
age: number;
}
Use async/await for asynchronous code for better readability and error handling.
Organize code into modules and use explicit import and export statements.
Ensuring a consistent development environment and utilizing static analysis tools are crucial steps for maintaining high code quality in TypeScript projects.
Static analysis tools help identify potential issues early in the development process. For TypeScript, several tools are particularly effective:
- TSLint: A linter that checks TypeScript code for readability, maintainability, and functionality errors.
- ESLint: A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript/TypeScript.
To further enhance your TypeScript development skills and knowledge, consider exploring the following resources:
- TypeScript Documentation: The official TypeScript documentation, offering in-depth guides and reference materials.
- DefinitelyTyped: A repository of high-quality TypeScript type definitions.