--- paths: - "**/*.ts" - "**/*.tsx" - "**/*.js" - "**/*.jsx" --- # Estilo de Código en TypeScript/JavaScript > Este archivo extiende [common/coding-style.md](../common/coding-style.md) con contenido específico de TypeScript/JavaScript. ## Tipos e Interfaces Usar tipos para hacer las APIs públicas, modelos compartidos y props de componentes explícitos, legibles y reutilizables. ### APIs Públicas - Agregar tipos de parámetros y retorno a funciones exportadas, utilidades compartidas y métodos públicos de clases - Dejar que TypeScript infiera tipos obvios de variables locales - Extraer formas de objetos inline repetidas en tipos o interfaces nombradas ```typescript // INCORRECTO: Función exportada sin tipos explícitos export function formatUser(user) { return `${user.firstName} ${user.lastName}` } // CORRECTO: Tipos explícitos en APIs públicas interface User { firstName: string lastName: string } export function formatUser(user: User): string { return `${user.firstName} ${user.lastName}` } ``` ### Interfaces vs. Type Aliases - Usar `interface` para formas de objetos que puedan ser extendidas o implementadas - Usar `type` para uniones, intersecciones, tuplas, tipos mapeados y tipos utilitarios - Preferir uniones de literales de string sobre `enum` a menos que se requiera un `enum` para interoperabilidad ```typescript interface User { id: string email: string } type UserRole = 'admin' | 'member' type UserWithRole = User & { role: UserRole } ``` ### Evitar `any` - Evitar `any` en el código de aplicación - Usar `unknown` para entrada externa o no confiable, luego estrecharlo de forma segura - Usar genéricos cuando el tipo de un valor depende del llamador ```typescript // INCORRECTO: any elimina la seguridad de tipos function getErrorMessage(error: any) { return error.message } // CORRECTO: unknown fuerza estrechamiento seguro function getErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message } return 'Unexpected error' } ``` ### Props de React - Definir las props de componentes con una `interface` o `type` nombrado - Tipar las props de callback explícitamente - No usar `React.FC` a menos que haya una razón específica para hacerlo ```typescript interface User { id: string email: string } interface UserCardProps { user: User onSelect: (id: string) => void } function UserCard({ user, onSelect }: UserCardProps) { return } ``` ### Archivos JavaScript - En archivos `.js` y `.jsx`, usar JSDoc cuando los tipos mejoran la claridad y una migración a TypeScript no es práctica - Mantener JSDoc alineado con el comportamiento en tiempo de ejecución ```javascript /** * @param {{ firstName: string, lastName: string }} user * @returns {string} */ export function formatUser(user) { return `${user.firstName} ${user.lastName}` } ``` ## Inmutabilidad Usar el operador spread para actualizaciones inmutables: ```typescript interface User { id: string name: string } // INCORRECTO: Mutación function updateUser(user: User, name: string): User { user.name = name // ¡MUTACIÓN! return user } // CORRECTO: Inmutabilidad function updateUser(user: Readonly, name: string): User { return { ...user, name } } ``` ## Manejo de Errores Usar async/await con try-catch y estrechar errores unknown de forma segura: ```typescript interface User { id: string email: string } declare function riskyOperation(userId: string): Promise function getErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message } return 'Unexpected error' } const logger = { error: (message: string, error: unknown) => { // Reemplazar con tu logger de producción (por ejemplo, pino o winston). } } async function loadUser(userId: string): Promise { try { const result = await riskyOperation(userId) return result } catch (error: unknown) { logger.error('Operation failed', error) throw new Error(getErrorMessage(error)) } } ``` ## Validación de Entrada Usar Zod para validación basada en esquemas e inferir tipos desde el esquema: ```typescript import { z } from 'zod' const userSchema = z.object({ email: z.string().email(), age: z.number().int().min(0).max(150) }) type UserInput = z.infer const validated: UserInput = userSchema.parse(input) ``` ## Console.log - Sin sentencias `console.log` en código de producción - Usar librerías de logging apropiadas en su lugar - Ver hooks para detección automática