Lecciones del módulo (2/2)
Tipos de Utilidad
TypeScript proporciona varios tipos de utilidad globales (Utility Types) para facilitar las transformaciones de tipo comunes. Estos tipos son genéricos y permiten crear nuevos tipos a partir de los existentes de forma declarativa.
Los cinco tipos de utilidad más utilizados son:
1. Partial<T>
Hace que todas las propiedades de un tipo T sean opcionales. Es extremadamente útil para funciones de actualización (update/patch) donde el usuario podría proporcionar solo un subconjunto de campos:
interface User {
id: number;
name: string;
email: string;
}
// Todas las propiedades de User se vuelven opcionales: { id?: number; name?: string; email?: string; }
type UserUpdate = Partial<User>;2. Readonly<T>
Hace que todas las propiedades de un tipo T sean de solo lectura (readonly). Cualquier intento de reasignar una propiedad causará un error del compilador en tiempo de compilación:
interface Point {
x: number;
y: number;
}
const p: Readonly<Point> = { x: 10, y: 20 };
// p.x = 5; // Error: no se puede asignar a 'x' porque es una propiedad de solo lectura3. Pick<T, Keys>
Crea un tipo seleccionando solo un conjunto específico de claves (representadas por una unión de cadenas) del tipo T:
interface Article {
id: number;
title: string;
content: string;
views: number;
}
// Selecciona solo 'title' y 'views': { title: string; views: number; }
type ArticlePreview = Pick<Article, 'title' | 'views'>;4. Omit<T, Keys>
Crea un tipo eliminando un conjunto específico de claves del tipo T. Es el opuesto de Pick:
interface Product {
id: number;
name: string;
price: number;
secretVendorCode: string;
}
// Elimina 'secretVendorCode': { id: number; name: string; price: number; }
type PublicProduct = Omit<Product, 'secretVendorCode'>;5. Record<Keys, Type>
Crea un tipo de objeto cuyas claves son Keys y cuyos valores son de tipo Type. Es muy útil para mapear claves a valores, representar diccionarios o tablas hash (key-value maps):
type Page = 'home' | 'about' | 'contact';
interface PageInfo {
title: string;
}
// Crea un diccionario con claves 'home' | 'about' | 'contact' y valores PageInfo
const nav: Record<Page, PageInfo> = {
home: { title: 'Home Page' },
about: { title: 'About Us' },
contact: { title: 'Contact Us' },
};Pruébalo tú mismo
Ejercicio 1: Actualización de perfil con Partial
Completa la función updateProfile que acepta un perfil original (Profile) y un objeto de actualizaciones (updates) donde todos los campos de Profile son opcionales. Debe devolver un nuevo objeto Profile que combine las propiedades originales con las actualizaciones.
Mostrar pista
Usa el tipo de utilidad Partial<Profile> para el parámetro updates, y el operador spread para unir los objetos: { ...original, ...updates }.
Solución disponible después de 3 intentos
Ejercicio 2: Eliminación de campos sensibles con Omit
Dado el tipo UserAccount, define un alias de tipo llamado SafeUser que omita la propiedad sensible passwordHash.
Mostrar pista
Usa type SafeUser = Omit<UserAccount, 'passwordHash'>; para omitir el campo especificado.
Solución disponible después de 3 intentos
Ejercicio 3: Configuración pública con Pick y Readonly
Dado el tipo AppConfig, define un alias de tipo llamado PublicConfig que sea una versión de solo lectura (Readonly) que contenga solo las propiedades apiEndpoint y port seleccionadas mediante Pick.
Mostrar pista
Usa type PublicConfig = Readonly<Pick<AppConfig, 'apiEndpoint' | 'port'>>;
Solución disponible después de 3 intentos
Ejercicio 4: Diccionario de usuarios con Record e Readonly
Dada una interfaz User con los campos id: number y name: string, crea un tipo ReadOnlyUser que haga que todos los campos de User sean de solo lectura. Luego, crea un tipo UserRegistry que represente un diccionario donde la clave es un string (por ejemplo, el id textual) y el valor es un ReadOnlyUser.
Mostrar pista
Usa Readonly<User> para definir ReadOnlyUser, y Record<string, ReadOnlyUser> para el diccionario.
Solución disponible después de 3 intentos