Pular para o conteúdo
TypeScript

Path Aliases no TypeScript: Setup com @/

Configure path aliases no tsconfig e nunca mais escreva ../../../. Guia prático com @/ convention, Next.js, Jest e Node.js pra deixar seus imports limpos.

Por que isso é importante

Path Aliases no TypeScript: Setup com @/. Configure path aliases no tsconfig e nunca mais escreva ../../../. Guia prático com @/ convention, Next.js, Jest e Node.js pra deixar seus imports limpos.

O Que São Path Aliases no TypeScript

Path aliases são atalhos de importação que você define no tsconfig.json. Em vez de navegar por pastas com pontos e barras, você cria um prefixo curto que aponta direto pra raiz do projeto ou pra pastas específicas.

O TypeScript resolve esses aliases em tempo de compilação. O compilador sabe que @/utils/format na verdade significa src/utils/format. O código fica legível e a resolução de módulos continua funcionando normalmente.

A convenção mais usada é o @/ apontando pra pasta src/. Mas dá pra criar quantos aliases quiser: @components, @utils, @services — cada um apontando pra uma pasta diferente. A estrutura do projeto fica explícita nos próprios imports.

Como Configurar Path Aliases Passo a Passo

A configuração tem duas partes: o tsconfig.json pro TypeScript entender os aliases, e a ferramenta de build/runtime pra resolver os módulos corretamente.

  1. Passo 1 - Defina o baseUrl no tsconfig.json: Adicione "baseUrl": "." no compilerOptions. Isso diz pro TypeScript que a raiz das importações é o diretório do projeto. Sem baseUrl, o paths não funciona.
  2. Passo 2 - Configure o paths com seus aliases: Dentro de compilerOptions, adicione o objeto paths com cada alias mapeado. O padrão é "@/*": ["src/*"] pra mapear @/ à pasta src/.
  3. Passo 3 - Configure a ferramenta de build: O TypeScript só resolve tipos com paths — ele não reescreve os imports no JavaScript gerado. Você precisa configurar sua ferramenta de build (Webpack, Vite, Next.js) pra resolver os aliases em runtime.
  4. Passo 4 - Configure o Jest se usar testes: O Jest não lê o tsconfig automaticamente. Adicione moduleNameMapper no jest.config pra mapear os mesmos aliases.
  5. Passo 5 - Teste imports em todos os contextos: Compile com tsc, rode os testes com Jest e inicie o dev server. Se algum contexto quebrar, o alias não tá configurado nele.

Configuração Completa do tsconfig.json

Vamos ao código. Essa é a configuração que funciona pra maioria dos projetos TypeScript.

Setup Básico com @/ Convention

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist",
    "rootDir": "./src",

    // Path Aliases - a mágica tá aqui
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"],
      "@services/*": ["src/services/*"],
      "@types/*": ["src/types/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

O asterisco no path é um wildcard. "@/*": ["src/*"] significa: qualquer coisa depois de @/ vai ser resolvida dentro de src/. Então @/utils/format vira src/utils/format.

Múltiplos Aliases Para Projetos Grandes

// tsconfig.json - projeto com muitos módulos
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@api/*": ["src/api/*"],
      "@config/*": ["src/config/*"],
      "@hooks/*": ["src/hooks/*"],
      "@lib/*": ["src/lib/*"],
      "@models/*": ["src/models/*"],
      "@store/*": ["src/store/*"],
      "@styles/*": ["src/styles/*"]
    }
  }
}

// Agora seus imports ficam assim:
import { useAuth } from '@hooks/useAuth';
import { UserModel } from '@models/User';
import { apiClient } from '@api/client';
import { theme } from '@styles/theme';

Com aliases nomeados, qualquer dev que abrir o código entende de onde vem cada import. A estrutura do projeto fica transparente.

Integração com Next.js

Next.js tem suporte nativo a path aliases. Ele lê o tsconfig.json e resolve os paths automaticamente — tanto no server quanto no client. Zero configuração extra no build.

// tsconfig.json (Next.js já entende isso nativamente)
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

// Uso nos componentes:
import { Button } from '@/components/ui/Button';
import { useUser } from '@/hooks/useUser';
import { cn } from '@/lib/utils';

// Se você usa o App Router com pasta src/:
// src/app/page.tsx
// src/components/Button.tsx
// O alias @/ aponta pra src/ automaticamente

// Next.js 13+ com create-next-app já cria o tsconfig
// com @/* configurado. Só usar.

Se você tá usando Next.js, essa é a configuração mais simples de todas. O create-next-app já pergunta se você quer usar @/ aliases e configura tudo sozinho.

Integração com Jest e moduleNameMapper

O Jest é o ponto que mais dá problema com path aliases. Ele não lê o tsconfig.json por padrão. Você precisa espelhar os aliases no jest.config manualmente.

// jest.config.ts
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',

  // Espelhar os paths do tsconfig.json
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@components/(.*)$': '<rootDir>/src/components/$1',
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',
    '^@services/(.*)$': '<rootDir>/src/services/$1',
    '^@types/(.*)$': '<rootDir>/src/types/$1',
  },

  // Ou use ts-jest pathsToModuleNameMapper:
  // moduleNameMapper: pathsToModuleNameMapper(
  //   compilerOptions.paths,
  //   { prefix: '<rootDir>/' }
  // ),
};

export default config;

O ts-jest tem uma função auxiliar chamada pathsToModuleNameMapper que lê os paths do tsconfig e converte automaticamente pro formato do Jest. Isso evita manter dois mapeamentos iguais em sincronia manual.

Usando pathsToModuleNameMapper Automatizado

// jest.config.ts - abordagem automatizada
import { pathsToModuleNameMapper } from 'ts-jest';
import { compilerOptions } from './tsconfig.json';

export default {
  preset: 'ts-jest',
  testEnvironment: 'node',
  modulePaths: ['<rootDir>'],
  moduleNameMapper: pathsToModuleNameMapper(
    compilerOptions.paths,
    { prefix: '<rootDir>/' }
  ),
};

// Agora quando você adiciona um novo alias no tsconfig,
// o Jest pega automaticamente. Zero manutenção extra.

Integração com Node.js Puro (module-alias)

Em projetos Node.js sem bundler, os aliases do tsconfig não funcionam em runtime. O JavaScript gerado ainda tenta resolver @/utils/format como um módulo real — e quebra. Você precisa de um pacote extra.

// Instalar module-alias
// npm install module-alias
// npm install -D @types/module-alias

// package.json - mapear aliases
{
  "_moduleAliases": {
    "@": "dist",
    "@components": "dist/components",
    "@utils": "dist/utils",
    "@services": "dist/services"
  }
}

// src/index.ts - registrar aliases ANTES de qualquer import
import 'module-alias/register';

import { startServer } from '@/server';
import { connectDB } from '@services/database';

async function main() {
  await connectDB();
  await startServer();
}

main();

Repare que os aliases no package.json apontam pra dist/ (pasta de build), não pra src/. Em runtime, o Node executa o JavaScript compilado, não o TypeScript original. Os caminhos precisam bater com a estrutura de saída.

Alternativa Mais Moderna: tsconfig-paths

// Instalar tsconfig-paths
// npm install -D tsconfig-paths

// Opção 1: Rodar com ts-node + tsconfig-paths
// npx ts-node -r tsconfig-paths/register src/index.ts

// Opção 2: Registrar no código
// src/register-paths.ts
import { register } from 'tsconfig-paths';
import { compilerOptions } from '../tsconfig.json';

register({
  baseUrl: compilerOptions.baseUrl,
  paths: compilerOptions.paths,
});

// Opção 3: Script no package.json
// {
//   "scripts": {
//     "dev": "ts-node -r tsconfig-paths/register src/index.ts",
//     "start": "node -r tsconfig-paths/register dist/index.js"
//   }
// }

O tsconfig-paths é mais elegante porque lê direto do tsconfig.json. Você não precisa duplicar os mapeamentos. Uma fonte de informação só.

Erros Comuns com Path Aliases

Armadilhas que pegam todo mundo

Esquecer o baseUrl: sem "baseUrl": "." no tsconfig, o paths é completamente ignorado. Esse é o erro número 1. Se seus aliases não funcionam, confira o baseUrl primeiro.

Aliases funcionam no editor mas quebram em runtime: o TypeScript resolve os types corretamente, mas o Node.js não sabe o que é @/. Você precisa de module-alias, tsconfig-paths ou um bundler configurado pra resolver os aliases no JavaScript gerado.

moduleNameMapper do Jest fora de sincronia: quando você adiciona um alias novo no tsconfig e esquece de atualizar o jest.config, os testes quebram. Use pathsToModuleNameMapper do ts-jest pra manter tudo sincronizado automaticamente.

Caminho errado no paths: "@/*": ["src/*"] exige que baseUrl seja ".". Se baseUrl for "src", o path deve ser "./*". A combinação errada faz o TypeScript resolver pra um lugar que não existe.

Conflito com módulos do node_modules: se seu alias tem o mesmo nome de um pacote npm, o TypeScript pode resolver pro pacote em vez do seu arquivo. Evite aliases genéricos como "utils" — prefira "@utils" com prefixo.

Checklist de Path Aliases

  • baseUrl definido como "." no tsconfig.json
  • paths configurado com aliases desejados (@/, @components/, etc.)
  • Ferramenta de build configurada pra resolver aliases (Next.js, Webpack, Vite)
  • Jest configurado com moduleNameMapper espelhando os paths
  • Aliases apontando pra dist/ em runtime com Node.js puro
  • Imports antigos com ../../../ refatorados pra usar aliases
  • Compilação com tsc passando sem erros
  • Testes com Jest rodando com aliases resolvidos
  • Dev server iniciando corretamente com aliases

Organização Profissional de Imports

Path aliases são um sinal de maturidade no projeto. No CrazyStack, cada módulo é organizado com aliases claros desde o início. Você aprende a montar uma arquitetura limpa com TypeScript, Node.js e React — do setup do tsconfig até o deploy final.

Chega de ../../../ no código. Configure uma vez, aproveite pra sempre.

Perguntas frequentes

O Que São Path Aliases no TypeScript

Path aliases são atalhos de importação que você define no tsconfig.json. Em vez de navegar por pastas com pontos e barras, você cria um prefixo curto que aponta direto pra raiz do projeto ou pra pastas específicas. O TypeScript resolve esses aliases em tempo de compilação. O compilador sabe que @/utils/format na verdade significa src/utils/format. O código fica legível e a resolução de módulos continua funcionando normalmente. A convenção mais usada é o @/ apontando pra pasta src/. Mas dá pra criar quantos aliases quiser: @components, @utils, @services — cada um apontando pra uma pasta diferente. A estrutura do projeto fica explícita nos próprios imports.

Como Configurar Path Aliases Passo a Passo

A configuração tem duas partes: o tsconfig.json pro TypeScript entender os aliases, e a ferramenta de build/runtime pra resolver os módulos corretamente.