← TypeScript EspañolChapter 12 of 12

Mejores Practicas

## Objetivos de Aprendizaje - Escribir TypeScript limpio y mantenible - Seguir convenciones de nomenclatura - Dominar la seguridad de tipos - Aplicar pruebas efectivas - Migrar desde JavaScript ## Estilo de Codigo ### Convenciones de Nomenclatura ```typescript // Clases: PascalCase class BankAccount { } // Interfaces: PascalCase (o a veces con prefijo I) interface UserService { } interface IUser { } // Alternativa: con prefijo I // Variables y funciones: camelCase let accountBalance: number; function calculateInterest() { } // Constantes: UPPER_SNAKE_CASE const MAX_RETRY_COUNT = 3; const API_BASE_URL = "https://api.example.com"; // Alias de tipo y enums: PascalCase type UserRole = "admin" | "user"; enum HttpStatus { Ok, NotFound } ``` ### Formato ```typescript // Usar 2 o 4 espacios consistentemente // Longitud de linea: ~100 caracteres maximo // Una declaracion por linea let age: number; let name: string; // Llaves siempre en la misma linea if (condition) { doSomething(); } else { doOther(); } ``` ## Seguridad de Tipos ### Modo Strict ```json { "compilerOptions": { "strict": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true } } ``` ### Evitar Any ```typescript // Mal function processData(data: any): any { return data; } // Bien function processData(data: T): T { return data; } // Si debes usar any function processData(data: unknown): unknown { return data; } ``` ### Inferencia de Tipos ```typescript // TypeScript infiere: let x = 10 es number let x = 10; // x = "hola"; // Error // Explicito cuando sea necesario let a: number | string; a = 10; a = "hola"; ``` ## Interfaces vs Alias de Tipo ### Usar Interface para Objetos ```typescript interface User { id: number; name: string; email: string; } ``` ### Usar Type para Uniones y Tuplas ```typescript type ID = string | number; type Point = [number, number]; type Callback = () => void; ``` ## Funciones ### Parametros y Retornos Tipados ```typescript // Bien: tipos explicitos function add(a: number, b: number): number { return a + b; } // Mal: confiar en inferencia const add = (a, b) => a + b; ``` ### Parametros Opcionales ```typescript // Opcional con ? function greet(name?: string): string { return name ? `Hola, ${name}!` : "Hola!"; } // Valores por defecto function createUser(name: string, role: string = "usuario") { return { name, role }; } ``` ## Clases ### Encapsulacion ```typescript class BankAccount { private balance: number = 0; constructor(initialBalance: number = 0) { this.balance = initialBalance; } deposit(amount: number): void { if (amount > 0) { this.balance += amount; } } withdraw(amount: number): boolean { if (amount > 0 && amount <= this.balance) { this.balance -= amount; return true; } return false; } getBalance(): number { return this.balance; } } ``` ### readonly para Constantes ```typescript class Config { readonly API_URL = "https://api.example.com"; readonly MAX_RETRIES = 3; } ``` ## Enums ### Usar Const Enums ```typescript const enum Status { Active, Pending, Completed } if (status === Status.Active) { // ... } ``` ### Enums de Cadena para Flexibilidad ```typescript enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" } ``` ## Genericos ### Restringir Cuando Sea Necesario ```typescript // Generico con restriccion function logLength(arg: T): T { console.log(arg.length); return arg; } logLength("hola"); // OK logLength([1, 2, 3]); // OK // logLength(123); // Error ``` ### Usar Tipos de Utilidad ```typescript // No reimplementar type PartialUser = Partial; type UserPreview = Pick; type UserWithoutEmail = Omit; ``` ## Manejo de Errores ### Tipos Especificos ```typescript try { JSON.parse(invalidJson); } catch (error) { if (error instanceof SyntaxError) { console.error("Error de sintaxis JSON:", error.message); } else { throw error; } } ``` ### Patron Result ```typescript type Result = | { success: true; value: T } | { success: false; error: E }; function divide(a: number, b: number): Result { if (b === 0) { return { success: false, error: new Error("Division por cero") }; } return { success: true, value: a / b }; } ``` ## Manejo de Null ### Encadenamiento Opcional ```typescript interface User { address?: { city: string; }; } let city = user?.address?.city; // undefined si falta ``` ### Fusion Nula ```typescript let name = userName ?? "Anonimo"; let count = items.length ?? 0; ``` ### Evitar Asercion No-nula ```typescript // Arriesgado let name = value!; // Mejor if (value !== null && value !== undefined) { let name = value; } ``` ## Migracion desde JavaScript ### Paso 1: Anadir tsconfig.json ```json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": false, "allowJs": true } } ``` ### Paso 2: Habilitar checkJs ```json { "compilerOptions": { "checkJs": true } } ``` ### Paso 3: Anadir Anotaciones de Tipo ```javascript // Antes (JavaScript) function add(a, b) { return a + b; } ``` ```typescript // Despues (TypeScript) function add(a: number, b: number): number { return a + b; } ``` ### Paso 4: Habilitar Modo Strict ```json { "compilerOptions": { "strict": true } } ``` ## Pruebas ### Con Jest ```typescript // calculator.ts export function add(a: number, b: number): number { return a + b; } // calculator.test.ts import { add } from "./calculator"; test("suma dos numeros", () => { expect(add(2, 3)).toBe(5); }); ``` ### Mocks Tipados ```typescript interface UserService { getUser(id: number): Promise; } function getUserWithCache( id: number, service: UserService ): Promise { // Implementacion } ``` ## Documentacion ### JSDoc con Tipos ```typescript /** * Calcula el area de un rectangulo. * * @param width - El ancho del rectangulo * @param height - La altura del rectangulo * @returns El area (width * height) * @throws {Error} Si width o height son negativos */ function rectangleArea(width: number, height: number): number { if (width < 0 || height < 0) { throw new Error("Las dimensiones deben ser positivas"); } return width * height; } ``` ## Herramientas ### ESLint ```json { "parser": "@typescript-eslint/parser", "rules": { "no-unused-vars": "error", "prefer-const": "error" } } ``` ### Prettier ```json { "semi": true, "singleQuote": true, "trailingComma": "es5" } ``` ## Resumen - Habilitar `strict: true` para seguridad de tipos - Preferir interfaces para formas de objetos - Usar type para uniones, tuplas, primitivos - Evitar `any`, usar `unknown` en su lugar - Usar encadenamiento opcional y fusion nula - Escribir funciones puras cuando sea posible - Usar `readonly` para constantes - Documentar APIs publicas con JSDoc - Probar funciones tipadas - Migrar gradualmente desde JavaScript

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →