Styling Guides

Naming Conventions

Rules for naming variables, functions, classes, and files that communicate intent clearly.

Overview

Consistent naming reduces the cognitive load of reading unfamiliar code. Well-named identifiers communicate intent without requiring a comment. The primary conventions are camelCase (JavaScript/TypeScript variables and functions), PascalCase (classes and React components), snake_case (Ruby variables and methods, Python, SQL), and kebab-case (CSS classes, URL paths, file names in JavaScript projects).

Origin

Naming conventions in programming trace to the Hungarian Notation system (Charles Simonyi, Xerox PARC, 1970s) which prefixed identifiers with type codes. Microsoft adopted it for Windows API (1980s). The modern preference for expressive names over type prefixes came from "Clean Code" (Robert Martin, 2008) and was reinforced by IDE tooling that makes type information available on hover.

Examples

Naming conventions across TypeScript contexts

// Variables and functions: camelCase
const maxRetryCount = 3;
const userEmailAddress = 'alice@example.com';
function calculateOrderTotal(items: OrderItem[]): number { return 0; }

// Constants: SCREAMING_SNAKE_CASE for true module-level constants
const MAX_UPLOAD_SIZE_BYTES = 10 * 1024 * 1024;
const HTTP_STATUS_OK = 200;

// Classes and interfaces: PascalCase
class UserRepository {}
interface PaymentGateway {}
type OrderStatus = 'pending' | 'confirmed' | 'fulfilled';

// React components: PascalCase, props interface suffixed with Props
interface ButtonProps { label: string; onClick: () => void; }
function SubmitButton({ label, onClick }: ButtonProps) { return null; }

// Private class members: prefix with _ (TypeScript convention for runtime privacy)
class Session {
  private _tokenExpiry: Date;
  #refreshToken: string; // ES2022 hard private

  constructor(token: string, expiry: Date) {
    this.#refreshToken = token;
    this._tokenExpiry = expiry;
  }
}

TypeScript uses _ prefix for private members by convention, but # for true hard-private fields (ES2022). The distinction matters: # prevents access even via reflection; private is compile-time only.

Ruby naming conventions with method suffixes

# Variables, methods, symbols: snake_case
user_email = 'alice@example.com'
order_count = 0

# Constants and classes: PascalCase
MAX_CONNECTIONS = 100
class UserRepository; end
module Billing; end

# Predicate methods: trailing ?
def active? = status == :active
def admin? = role == :admin

# Bang methods: trailing ! (mutate receiver or raise on failure)
def save! = persist! || raise(PersistenceError, 'Save failed')
def normalize! = @name.strip!.downcase!

# Private methods convention: leading _ in some codebases, or just private
class InvoiceService
  def generate(order)
    subtotal = _calculate_subtotal(order.items)
    _apply_tax(subtotal, order.tax_rate)
  end

  private

  def _calculate_subtotal(items) = items.sum { |i| i.price * i.qty }
  def _apply_tax(amount, rate) = amount * (1 + rate)
end

Ruby's ? and ! suffixes are enforced by convention, not the language. They communicate contracts: ? returns true/false and never raises; ! raises on failure (ActiveRecord pattern) or mutates in place (Array#sort!).

Use Cases

  • 01Onboarding new engineers: a consistent convention means unfamiliar code follows predictable patterns, reducing time to productive contribution
  • 02Code review: reviewers can focus on logic rather than debating casing; a linter (ESLint, RuboCop) enforces the convention automatically
  • 03Auto-import and tooling: IDEs rely on naming patterns to infer what to import; PascalCase tells TypeScript's auto-importer that something is likely a class or component
  • 04Cross-language projects: explicitly documenting conventions per language layer (snake_case Ruby, camelCase TypeScript, kebab-case CSS) prevents style leakage between layers

When Not to Use

  • //Do not force a convention where the ecosystem has a strong established norm (SQL columns are snake_case even in a camelCase TypeScript project)
  • //Do not use Hungarian notation prefixes (strName, iCount) in strongly-typed languages where the type is known from the declaration
  • //Do not abbreviate aggressively; usrNm is not better than userName regardless of the convention

Technical Notes

  • ESLint's @typescript-eslint/naming-convention rule enforces casing, required prefixes/suffixes per identifier type (variable, function, class, interface, enum) and can be configured per scope
  • RuboCop's Naming cops (Naming/MethodName, Naming/VariableName) enforce snake_case and flag violations with line numbers; --autocorrect-all fixes some categories automatically
  • Abbreviations in names should be treated as words for casing purposes: HttpClient not HTTPClient, parseUrl not parseURL (Google Java Style Guide, Angular style guide both specify this)
  • File naming: React components in PascalCase files (UserCard.tsx), utility functions in camelCase (formatDate.ts), and constants in SCREAMING_SNAKE_CASE (HTTP_CODES.ts) is the Angular and Create React App convention