code-organization
Code Organization:
TypeScript Code Organization:
Modularization:
By splitting code into modules, each file represents a module and can export variables, functions, classes, or interfaces to be used elsewhere.
// math.ts
export function add(x: number, y: number): number {
return x + y;
}
// Use in another file
import { add } from './math';
Use of Namespaces:
Namespaces provide a way to bundle related functionalities under a single named context.
// shapes.ts
namespace Shapes {
export class Rectangle {
// ...
}
}
// Use in another file
/// <reference path="shapes.ts" />
let rect = new Shapes.Rectangle();
Directory Structure:
Organize TypeScript files into folders that reflect the content's purpose, like models, services, or utilities.
/src
/models
user.ts
/services
userService.ts
/utilities
utils.ts
Barrel Exports:
Barrels allow you to re-export several modules from a single file.
// index.ts in models directory
export * from './user';
export * from './account';
// Use in another file
import { User, Account } from '../models';
Consistent Naming Conventions:
Consistently name your entities, such as using PascalCase for classes and interfaces, and camelCase for functions and variables.
// UserService.ts
export class UserService {
// ...
}
// IUserInfo.ts
export interface IUserInfo {
// ...
}
Aliases for Paths:
Use path aliases to simplify imports and avoid relative path hell.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@models": ["src/models"],
"@services": ["src/services"]
}
}
}
// Use in another file
import { UserService } from '@services/UserService';
Declaring Types and Interfaces:
Place types and interfaces either next to where they're used or in a dedicated file for shared types.
// types.ts for shared types
export interface IUser {
// ...
}
// userService.ts for specific use
interface IServiceResponse {
// ...
}
Incremental Adoption:
Convert JavaScript files to TypeScript by renaming
.js
to.ts
and gradually adding type annotations.
// Before: function.js
function greet(name) {
return 'Hello, ' + name;
}
// After: function.ts
function greet(name: string): string {
return 'Hello, ' + name;
}
Single Responsibility:
Each module should have a single purpose. Avoid cluttering a module with unrelated functions or classes.
// good
export function calculateArea(width: number, height: number): number {
return width * height;
}
// bad
export function calculateAreaAndSendEmail(width: number, height: number): number {
// ... does two things
}
Avoiding Deep Nesting:
Keep your folder structure shallow to make it easy to locate files.
// Preferred structure
/src
/components
/services
// Avoid deep nesting
/src
/components
/navigation
/sidebar
/items
Organizing your TypeScript project with these practices leads to a codebase that is easier to understand, navigate, and maintain. It can improve collaboration and efficiency when working on large-scale projects or within teams.
Continued TypeScript Code Organization:
Documentation:
Writing comments and maintaining documentation helps developers understand the higher-level architecture and the purpose behind code structures.
/**
* This module handles the authentication workflow.
* It interacts with the User model and the Auth service.
*/
// authManager.ts
export class AuthManager {
// ...
}
Leverage Project References:
TypeScript's project references can help you manage and separate parts of your application into smaller projects.
// tsconfig.json
{
"compilerOptions": {
// ...
},
"references": [
{ "path": "./core" },
{ "path": "./services" }
]
}
Strong Typing:
Utilize TypeScript's type system to its fullest by avoiding
any
and using detailed types.
// Avoid using 'any'
function processUser(user: any) {
// ...
}
// Use strong typing
interface User {
id: number;
name: string;
}
function processUser(user: User) {
// ...
}
Refactoring:
Refactor code to improve readability and maintainability, such as breaking down large functions into smaller, more focused functions.
// Before refactoring
function handleRequest(request: Request) {
// a lot of code handling various aspects of the request
}
// After refactoring
function parseRequest(request: Request) {
// ...
}
function validateRequest(parsedRequest: ParsedRequest) {
// ...
}
function processRequest(validatedRequest: ValidatedRequest) {
// ...
}
Code Reviews:
Peer reviews of code help maintain code quality and adherence to project standards.
// Code review checklist:
// - Follows naming conventions
// - Modules are well-documented
// - Functions are small and single-purposed
// - Types are used correctly and are not `any`
// - No unnecessary dependencies between modules
By applying these practices consistently, a TypeScript project can be kept clean, efficient, and understandable. Documentation, strong typing, and regular refactoring contribute to a robust codebase, while project references and code reviews can help in managing large and complex codebases with multiple developers.