Fumadocs + Code Hike
Backend

TypeScript

Linguagem tipada baseada em JavaScript para desenvolvimento escalável

O que é TypeScript?

TypeScript é um superconjunto tipado do JavaScript que compila para JavaScript puro. Desenvolvido pela Microsoft, adiciona tipos estáticos opcionais e recursos avançados de POO, permitindo detectar erros em tempo de desenvolvimento e melhorar a produtividade.

Por que utilizamos TypeScript na IngenioLab?

  • Detecção precoce de erros: Tipos ajudam a identificar bugs antes da execução
  • Melhor IntelliSense: Autocompletar e refatoração mais inteligentes
  • Código autodocumentado: Tipos servem como documentação viva
  • Escalabilidade: Facilita manutenção de projetos grandes
  • Compatibilidade: Todo JavaScript válido é TypeScript válido
  • Ecossistema: Excelente suporte em ferramentas e frameworks

Instalação e Configuração

1. Instalação global:

npm install -g typescript
# ou
npm install -D typescript # projeto específico

2. Verificar instalação:

tsc --version

3. Inicializar projeto TypeScript:

# Criar tsconfig.json
tsc --init
# ou manualmente
touch tsconfig.json

Configuração Padrão IngenioLab

tsconfig.json recomendado:

{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowImportingTsExtensions": true,
"noEmit": true,
"isolatedModules": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": false,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true,
"paths": {
"@/*": ["./src/*"],
"@/types/*": ["./src/types/*"],
"@/utils/*": ["./src/utils/*"]
}
},
"include": [
"src/**/*",
"tests/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.js"
]
}

Estrutura de Projeto Recomendada

projeto-typescript/
├── src/
│ ├── types/ # Definições de tipos
│ │ ├── index.ts
│ │ ├── api.ts
│ │ └── models.ts
│ ├── utils/ # Utilitários tipados
│ ├── services/ # Serviços de API
│ ├── components/ # Componentes (se React)
│ └── index.ts # Ponto de entrada
├── tests/
├── dist/ # JavaScript compilado
├── package.json
├── tsconfig.json
└── .gitignore

Padrões de Código IngenioLab

1. Definição de Tipos e Interfaces:

// types/api.ts
export interface User {
readonly id: string
name: string
email: string
createdAt: Date
preferences?: UserPreferences
}
export interface UserPreferences {
theme: 'light' | 'dark'
notifications: boolean
language: 'pt' | 'en' | 'es'
}
// Tipos utilitários
export type CreateUser = Omit<User, 'id' | 'createdAt'>
export type UpdateUser = Partial<Pick<User, 'name' | 'preferences'>>

2. Funções Tipadas:

// services/userService.ts
import { User, CreateUser, UpdateUser } from '@/types/api'
export class UserService {
async createUser(userData: CreateUser): Promise<User> {
// Implementação com tipos garantidos
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
})
if (!response.ok) {
throw new Error(`Failed to create user: ${response.statusText}`)
}
return await response.json() as User
}
async updateUser(id: string, updates: UpdateUser): Promise<User> {
// Tipos garantem que apenas campos válidos sejam atualizados
const response = await fetch(`/api/users/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates)
})
return await response.json() as User
}
}

3. Generics para Reutilização:

// utils/api.ts
export interface ApiResponse<T> {
data: T
status: number
message?: string
}
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
pagination: {
page: number
limit: number
total: number
hasNext: boolean
}
}
export async function apiRequest<T>(
url: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
})
const data = await response.json()
return {
data,
status: response.status,
message: data.message
}
}

4. Enums e Union Types:

// types/models.ts
export enum UserRole {
ADMIN = 'admin',
USER = 'user',
MODERATOR = 'moderator'
}
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
export type DatabaseStatus =
| 'connecting'
| 'connected'
| 'disconnected'
| 'error'
// Uso de discriminated unions
export type ApiResult<T> =
| { success: true; data: T }
| { success: false; error: string }

5. Classes com Tipagem:

// models/BaseModel.ts
export abstract class BaseModel {
public readonly id: string
public readonly createdAt: Date
public updatedAt: Date
constructor(id: string) {
this.id = id
this.createdAt = new Date()
this.updatedAt = new Date()
}
abstract validate(): boolean
protected touch(): void {
this.updatedAt = new Date()
}
}
// models/User.ts
import { BaseModel } from './BaseModel'
export class User extends BaseModel {
constructor(
id: string,
public name: string,
public email: string,
private _role: UserRole = UserRole.USER
) {
super(id)
}
get role(): UserRole {
return this._role
}
setRole(newRole: UserRole): void {
if (this._role === UserRole.ADMIN) {
this._role = newRole
this.touch()
}
}
validate(): boolean {
return this.name.length > 0 &&
this.email.includes('@') &&
Object.values(UserRole).includes(this._role)
}
}

Utilitários de Tipos Avançados

1. Conditional Types:

type NonNullable<T> = T extends null | undefined ? never : T
type ApiEndpoint<T extends string> = T extends `${infer R}Api`
? `/api/${Lowercase<R>}`
: never
type UserApi = ApiEndpoint<'UserApi'> // '/api/user'

2. Mapped Types:

type Optional<T> = {
[K in keyof T]?: T[K]
}
type Required<T> = {
[K in keyof T]-?: T[K]
}
type Readonly<T> = {
readonly [K in keyof T]: T[K]
}

3. Template Literal Types:

type EventName<T extends string> = `on${Capitalize<T>}`
type UserEvents = EventName<'click' | 'hover'> // 'onClick' | 'onHover'
type HttpStatus =
| `${2}${number}${number}` // 2xx
| `${4}${number}${number}` // 4xx
| `${5}${number}${number}` // 5xx

Comandos de Desenvolvimento

Compilação:

# Compilar uma vez
tsc
# Modo watch (recompila automaticamente)
tsc --watch
# Verificar tipos sem gerar arquivos
tsc --noEmit
# Compilar arquivo específico
tsc src/index.ts --outDir dist

Com ferramentas modernas:

# Usar ts-node para desenvolvimento
npm install -D ts-node
npx ts-node src/index.ts
# Com Bun (execução direta)
bun run src/index.ts
# Com Vite (para web)
npm run dev

Debugging e Ferramentas

1. ESLint + TypeScript:

npm install -D @typescript-eslint/eslint-plugin @typescript-eslint/parser
// .eslintrc.json
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"@typescript-eslint/recommended"
]
}

2. Prettier + TypeScript:

// .prettierrc
{
"semi": false,
"singleQuote": true,
"trailingComma": "es5",
"parser": "typescript"
}

3. Source Maps para debugging:

// tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false
}
}

Boas Práticas IngenioLab

1. ✅ Faça:

  • Use strict: true sempre
  • Prefira interface para definir contratos
  • Use type para unions e computed types
  • Sempre tipifique parâmetros de função
  • Use readonly para dados imutáveis
  • Prefira const assertions quando necessário

2. ❌ Evite:

  • any - use unknown se necessário
  • Function - tipifique assinaturas específicas
  • object - use interfaces específicas
  • Tipos implícitos em funções públicas

3. Exemplo prático:

// ✅ Correto
interface ApiConfig {
readonly baseUrl: string
timeout: number
retries?: number
}
const createApiClient = (config: ApiConfig): ApiClient => {
// implementação
}
// ❌ Evitar
const createApiClient = (config: any) => {
// sem tipagem
}

Migração JavaScript → TypeScript

1. Renomeie arquivos:

# .js → .ts
# .jsx → .tsx (para React)
find src -name "*.js" -exec sh -c 'mv "$1" "${1%.js}.ts"' _ {} \;

2. Configure tsconfig.json gradualmente:

{
"compilerOptions": {
"allowJs": true, // Permite JS durante migração
"checkJs": false, // Não verifica JS inicialmente
"strict": false, // Ative gradualmente
"noImplicitAny": false // Ative depois
}
}

3. Migre módulo por módulo:

  1. Adicione tipos aos parâmetros de função
  2. Defina interfaces para objetos
  3. Adicione tipos de retorno
  4. Ative strict mode