Skip to main content

code-organization

Code Organization:

TypeScript Code Organization:

  1. 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';
  1. 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();
  1. 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
  1. 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';
  1. 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 {
// ...
}
  1. 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';
  1. 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 {
// ...
}
  1. 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;
}
  1. 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
}
  1. 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:

  1. 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 {
// ...
}
  1. 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" }
]
}
  1. 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) {
// ...
}
  1. 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) {
// ...
}
  1. 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.