Kaique Mitsuo Silva Yamamoto
Arquitetura softwareFrontend webTypeScriptClean Code

Naming Conventions em TypeScript

Como nomear variáveis, funções, tipos e constantes de forma que o código se explique — exemplos full-stack.

Naming Conventions em TypeScript

"Nomes ruins são a maior fonte de confusão em código." — Robert C. Martin

O nome de uma variável, função ou tipo deve responder a três perguntas:

  1. O que é? (dado, função, classe, constante)
  2. O que faz? (ação, verificação, transformação)
  3. Do que precisa? (contexto, restrições)

Regras gerais

Nomes intencionais, não genéricos

// ❌ Genérico — não diz nada
const d = new Date();
const data = await fetch('/api/users');
const temp = users.filter(u => u.active);
const flag = true;

// ✅ Intencional — diz exatamente o que é
const currentDate = new Date();
const activeUsersResponse = await fetch('/api/users');
const activeUsers = users.filter(u => u.isActive);
const isSubscriptionActive = true;

Variáveis booleanas: prefixo is/has/can/should

O prefixo transforma a variável em uma pergunta que o leitor entende imediatamente.

// ❌ Sem prefixo — dúvida: é boolean ou string? É estado ou verificação?
const active = user.status === 'active';
const admin = user.role === 'admin';
const premium = user.plan !== 'free';

// ✅ Com prefixo — lê como frase
const isActive = user.status === 'active';
const isAdmin = user.role === 'admin';
const hasPremiumAccess = user.plan !== 'free';
const canEditDocument = user.role === 'admin' || document.authorId === user.id;
const shouldShowUpgradeBanner = !hasPremiumAccess && user.trialDaysRemaining < 7;

Funções: verbo + substantivo

// ❌ Substantivo puro — parece propriedade, não ação
const user(id: string) { /* ... */ }
const total(items: CartItem[]) { /* ... */ }

// ❌ Verbo genérico — não diz o que processa
function process(data: any) { /* ... */ }
function handle(event: any) { /* ... */ }
function doStuff(thing: any) { /* ... */ }

// ✅ Verbo + substantivo — diz exatamente o que faz
function getUserById(id: string): Promise<User | null> { /* ... */ }
function calculateCartTotal(items: CartItem[]): number { /* ... */ }
function validateEmailFormat(email: string): boolean { /* ... */ }
function formatCurrencyToBRL(amount: number): string { /* ... */ }

Prefixos comuns por contexto

PrefixoSignificadoExemplo
getBusca/obtém (pode retornar null)getUserById, getAuthToken
findBusca (pode não encontrar)findByEmail, findNearestStore
createCria novo registrocreateOrder, createNotification
updateAtualiza existenteupdateUserProfile, updateCartQuantity
delete/removeRemovedeleteUser, removeFromCart
is/has/can/shouldRetorna booleanisActive, hasPermission, canAccess
formatFormata para exibiçãoformatDateToBR, formatCurrency
parseConverte string para tipoparseJwt, parseCSV
validateVerifica validadevalidateEmail, validateCPF
handle/onReage a eventohandleSubmit, onPaymentSuccess
fetch/loadBusca de API/remotofetchProducts, loadUserData

Convenções por elemento

ElementoConvençãoExemplo
VariáveiscamelCaseuserName, activeUsers
FunçõescamelCase + verbogetUserById, calculateTotal
ClassesPascalCaseUserService, HttpClient
InterfacesPascalCase (sem I prefix)User, ApiResponse
TypesPascalCaseStatus, Currency, MouseEvent
EnumsPascalCaseOrderStatus, PaymentMethod
ConstantesUPPER_SNAKE_CASEMAX_RETRY_COUNT, API_BASE_URL
Private membersprefixo _ ou #_cache, #internalState
GenericsT + descriçãoT, TData, TError, TResponse
Arquivos de componentePascalCaseUserProfile.tsx, PaymentForm.tsx
Arquivos de utilidadekebab-caseformat-date.ts, validate-cpf.ts
Arquivos de hookcamelCase + prefixo useuseAuth.ts, useProducts.ts

Nomes em contextos full-stack

Frontend — Componentes e hooks

// ❌ Nomes ruins
function Comp1({ d }: any) {
  const [x, setX] = useState(null);
  const y = useCallback(() => { /* ... */ }, []);
  return <div onClick={y}>{d?.n}</div>;
}

// ✅ Nomes claros
interface UserCardProps {
  user: User;
  onSelect: (userId: string) => void;
}

function UserCard({ user, onSelect }: UserCardProps) {
  const [isExpanded, setIsExpanded] = useState(false);
  const handleSelect = useCallback(() => onSelect(user.id), [user.id, onSelect]);

  return (
    <div onClick={handleSelect}>
      <h3>{user.name}</h3>
      {isExpanded && <p>{user.email}</p>}
    </div>
  );
}

Backend — Services e repositories

// ❌ Nomes ruins
class Svc {
  async go(id: string) {
    const x = await this.repo.one(id);
    if (!x) throw new Error('no');
    return x;
  }
}

// ✅ Nomes claros
class OrderService {
  async getOrderWithItems(orderId: string): Promise<OrderWithItems | null> {
    const order = await this.orderRepository.findById(orderId);

    if (!order) {
      throw new NotFoundError(`Pedido ${orderId} não encontrado`);
    }

    const items = await this.orderItemRepository.findByOrderId(orderId);
    return { ...order, items };
  }
}

Tipos e enums

// ❌ Nomes ruins
type T = { n: string; a: number };
enum S { A, B, C }

// ✅ Nomes claros
interface UserProfile {
  name: string;
  age: number;
}

enum OrderStatus {
  Pending = 'pending',
  Processing = 'processing',
  Shipped = 'shipped',
  Delivered = 'delivered',
  Cancelled = 'cancelled',
}

Anti-padrões de nomenclatura

Anti-padrãoExemploProblema
Siglas obscurasusrMgt, procOrdNão dizem nada sem contexto
Números no finaluser1, data2Parecem duplicatas, não variantes
Nomes genéricosdata, result, temp, objQualquer coisa pode ter esse nome
Prefixos húngarosstrName, intAgeTypeScript já tem tipos — redundante
Negativas em booleanisNotActive, hasNoPermissionDifícil de ler com !: !isNotActive
Verbos em variáveisgetUser, calculateTotalParecem funções, não dados

Regra de ouro

Se você precisa de um comentário para explicar o que uma variável/função faz, o nome está ruim.

// ❌ Precisa de comentário
// Verifica se o usuário pode acessar o recurso
function check(u: User, r: Resource) { /* ... */ }

// ✅ O nome já é a documentação
function canUserAccessResource(user: User, resource: Resource): boolean { /* ... */ }

Referências

On this page