TypeScript en el Proyecto
Por qué TypeScript
Section titled “Por qué TypeScript”- Errores en compilación, no en producción: Si escribes
user.nmaeen vez deuser.name, TypeScript te avisa al instante - Autocomplete inteligente: Tu editor sabe exactamente qué propiedades tiene cada objeto
- Refactoring seguro: Renombra una propiedad y TypeScript te muestra todos los lugares que debes actualizar
- Documentación viva: Los tipos son documentación que nunca se desactualiza
Reglas del proyecto
Section titled “Reglas del proyecto”- Prohibido
any: Siempre. Usarunknownsi no conoces el tipo y hacer type narrowing - Tipar todo explícitamente: Props, emits, retornos de funciones, estado reactivo
- No
// @ts-ignore: Nunca. Soluciona el error de tipo real
Cómo se usan los tipos
Section titled “Cómo se usan los tipos”Props de componentes (obligatorio)
Section titled “Props de componentes (obligatorio)”interface Props { title: string count?: number // opcional variant?: 'primary' | 'secondary' // union literal}
const props = defineProps<Props>()Emits de componentes (obligatorio)
Section titled “Emits de componentes (obligatorio)”const emit = defineEmits<{ update: [value: string] // emit con payload close: [] // emit sin payload}>()Estado reactivo
Section titled “Estado reactivo”const items = ref<Course[]>([]) // array tipadoconst selected = ref<Course | null>(null) // puede ser nullconst isLoading = ref(false) // inferido como booleanServicios (tipo genérico del proyecto)
Section titled “Servicios (tipo genérico del proyecto)”// Firma genérica usada en la vertical configtype FunctionService<T, U = undefined> = U extends undefined ? (lang: LanguageCode) => Promise<T | null> : (lang: LanguageCode, params: U) => Promise<T | null>Esto significa: un servicio recibe siempre un idioma, opcionalmente parámetros, y retorna data o null.
Organización de tipos
Section titled “Organización de tipos”| Carpeta | Contiene | Ejemplo |
|---|---|---|
app/types/ | Tipos simples, unions, auxiliares | LanguageCode, AlertType, LoginData |
app/interfaces/ | Estructuras complejas de API | LoginResponse, Expert, Product |
app/interfaces/api/ | Contratos con Strapi | Responses tipadas del CMS |
Regla práctica
Section titled “Regla práctica”- ¿Objeto con múltiples propiedades que viene de API? →
interfaces/ - ¿Union type, enum, tipo auxiliar pequeño? →
types/
Tipos comunes del proyecto
Section titled “Tipos comunes del proyecto”type LanguageCode = 'es' | 'en' | 'pt-BR'type AlertType = 'error' | 'success'type HexColor = `#${string}`
// types/services.d.tstype FunctionService<T, U = undefined> = ...
// types/forms.d.tstype FormField = { valid: boolean; showError: boolean }Truco útil: as const
Section titled “Truco útil: as const”Para arrays o objetos que son constantes literales:
export const SUBSCRIPTION_TYPES = ['annual', 'monthly'] as const// Tipo inferido: readonly ['annual', 'monthly'] — no string[]
export const USER_ROLES = { ADMIN: 'admin', USER: 'user',} as constDerivar tipos automáticamente:
type SubscriptionType = (typeof SUBSCRIPTION_TYPES)[number] // 'annual' | 'monthly'type UserRole = (typeof USER_ROLES)[keyof typeof USER_ROLES] // 'admin' | 'user'Errores de tipo comunes y cómo resolverlos
Section titled “Errores de tipo comunes y cómo resolverlos”| Error | Solución |
|---|---|
Type 'X' is not assignable to type 'Y' | Verifica que el tipo del valor coincide con lo declarado |
Object is possibly 'null' | Usa optional chaining (?.) o un guard (if (obj)) |
Property does not exist on type | El tipo no tiene esa propiedad — verifica el nombre o amplía la interface |
Argument of type 'string' is not assignable to parameter of type 'LanguageCode' | Usa assertion (as LanguageCode) o valida el valor |