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# ounpm install -D typescript # projeto específico
2. Verificar instalação:
tsc --version
3. Inicializar projeto TypeScript:
# Criar tsconfig.jsontsc --init# ou manualmentetouch 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.tsexport interface User {readonly id: stringname: stringemail: stringcreatedAt: Datepreferences?: UserPreferences}export interface UserPreferences {theme: 'light' | 'dark'notifications: booleanlanguage: 'pt' | 'en' | 'es'}// Tipos utilitáriosexport type CreateUser = Omit<User, 'id' | 'createdAt'>export type UpdateUser = Partial<Pick<User, 'name' | 'preferences'>>
2. Funções Tipadas:
// services/userService.tsimport { User, CreateUser, UpdateUser } from '@/types/api'export class UserService {async createUser(userData: CreateUser): Promise<User> {// Implementação com tipos garantidosconst 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 atualizadosconst 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.tsexport interface ApiResponse<T> {data: Tstatus: numbermessage?: string}export interface PaginatedResponse<T> extends ApiResponse<T[]> {pagination: {page: numberlimit: numbertotal: numberhasNext: 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.tsexport 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 unionsexport type ApiResult<T> =| { success: true; data: T }| { success: false; error: string }
5. Classes com Tipagem:
// models/BaseModel.tsexport abstract class BaseModel {public readonly id: stringpublic readonly createdAt: Datepublic updatedAt: Dateconstructor(id: string) {this.id = idthis.createdAt = new Date()this.updatedAt = new Date()}abstract validate(): booleanprotected touch(): void {this.updatedAt = new Date()}}// models/User.tsimport { 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 = newRolethis.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 : Ttype ApiEndpoint<T extends string> = T extends `${infer R}Api`? `/api/${Lowercase<R>}`: nevertype 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 veztsc# Modo watch (recompila automaticamente)tsc --watch# Verificar tipos sem gerar arquivostsc --noEmit# Compilar arquivo específicotsc src/index.ts --outDir dist
Com ferramentas modernas:
# Usar ts-node para desenvolvimentonpm install -D ts-nodenpx 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: truesempre - Prefira
interfacepara definir contratos - Use
typepara unions e computed types - Sempre tipifique parâmetros de função
- Use
readonlypara dados imutáveis - Prefira
const assertionsquando necessário
2. ❌ Evite:
any- useunknownse necessárioFunction- tipifique assinaturas específicasobject- use interfaces específicas- Tipos implícitos em funções públicas
3. Exemplo prático:
// ✅ Corretointerface ApiConfig {readonly baseUrl: stringtimeout: numberretries?: number}const createApiClient = (config: ApiConfig): ApiClient => {// implementação}// ❌ Evitarconst 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:
- Adicione tipos aos parâmetros de função
- Defina interfaces para objetos
- Adicione tipos de retorno
- Ative
strictmode