← Volver al catálogo
WebReferenciaAvanzadoGratis

TypeScript: Tipos Avanzados

Guia completa del sistema de tipos avanzados de TypeScript: genericos, tipos condicionales, tipos mapeados, literales de plantilla y tipos utilitarios. Ideal para construir aplicaciones con seguridad de tipos en tiempo de compilacion.

Descargar SKILL.md

Descarga abierta · sin registro · para TypeScript, Node.js, Browser

// resultado_de_ejemplo

/**

  • CultivaSaaS — TypeScript Tipos Avanzados
  • Referencia práctica de patrones type-safe para el dashboard de marketing con IA.
  • Generado por CULTIVA IA · skill: typescript-tipos-avanzados */

// ============================================================ // 1. GENÉRICOS — API Client type-safe // ============================================================

/** Respuesta genérica del backend REST de CultivaSaaS */ interface ApiResponse { data: T; meta: { total: number; page: number; perPage: number; }; error?: string; }

/** Petición paginable genérica */ interface PaginatedRequest<TFilter = Record<string, unknown>> { page?: number; perPage?: number; filters?: TFilter; sortBy?: string; sortDir?: "asc" | "desc"; }

/** Cliente HTTP genérico type-safe */ async function apiGet( endpoint: string, params?: PaginatedRequest ): Promise<ApiResponse> { // Implementación real: fetch('/api/' + endpoint, { params }) return {} as ApiResponse; }

/** Extrae el tipo de datos de una ApiResponse */ type UnwrapApi = T extends ApiResponse ? D : never;

// Uso: // const res = await apiGet<Campaign[]>('campaigns', { page: 1, perPage: 20 }); // type CampaignData = UnwrapApi; // Campaign[]

// ============================================================ // 2. TIPOS CONDICIONALES — Validación de permisos por rol // ============================================================

type Role = "admin" | "manager" | "viewer";

/** Un admin puede hacer todo; manager, casi todo; viewer, solo leer */ type Permissions = R extends "admin" ? { read: true; write: true; delete: true; billing: true } : R extends "manager" ? { read: true; write: true; delete: false; billing: false } : { read: true; write: false; delete: false; billing: false };

type AdminPerms = Permissions<"admin">; // { read:true; write:true; delete:true; billing:true } type ViewerPerms = Permissions<"viewer">; // { read:true; write:false; delete:false; billing:false }

/** Extrae solo las keys donde el permiso es true */ type AllowedActions = { [K in keyof Permissions]: Permissions[K] extends true ? K : never; }[keyof Permissions];

type AdminActions = AllowedActions<"admin">; // "read" | "write" | "delete" | "billing" type ViewerActions = AllowedActions<"viewer">; // "read"

/** Inferencia del tipo de retorno de funciones de dominio */ type ReturnOf = T extends (...args: any[]) => infer R ? R : never;

function buildCampaignSummary(id: string) { return { id, status: "active" as const, clicks: 0, conversions: 0 }; }

type CampaignSummary = ReturnOf; // { id: string; status: "active"; clicks: number; conversions: number }

// ============================================================ // 3. TIPOS MAPEADOS — Entidades de CultivaSaaS // ============================================================

/** Modelo de campaña completo */ interface Campaign { id: string; name: string; status: "draft" | "active" | "paused" | "completed"; budget: number; startDate: Date; endDate: Date; channels: Channel[]; ownerId: string; createdAt: Date; updatedAt: Date; }

type Channel = "meta" | "google" | "tiktok" | "email" | "linkedin";

/** Formulario de creación: solo campos editables, todos opcionales */ type CreateCampaignForm = Partial< Omit<Campaign, "id" | "createdAt" | "updatedAt">

;

/** Vista pública de campaña: sin datos sensibles de owner */ type CampaignPublicView = Omit<Campaign, "ownerId" | "budget">;

/** Versión readonly para componentes de solo lectura */ type CampaignReadonly = Readonly;

/** Genera getters tipados para cualquier entidad */ type Getters = { [K in keyof T as get${Capitalize<string & K>}]: () => T[K]; };

type CampaignGetters = Getters<Pick<Campaign, "id" | "name" | "status">>; // { getId: () => string; getName: () => string; getStatus: () => "draft"|"active"|"paused"|"completed" }

/** Filtra solo las propiedades de tipo string de un objeto */ type StringProps = { [K in keyof T as T[K] extends string ? K : never]: T[K]; };

type CampaignStringFields = StringProps; // { id: string; name: string; status: ...; ownerId: string }

/** Marca campos como "sucios" para el formulario */ type DirtyFields = { [K in keyof T]?: boolean; };

type CampaignDirty = DirtyFields;

// ============================================================ // 4. TEMPLATE LITERAL TYPES — Eventos y rutas type-safe // ============================================================

/** Eventos de dominio generados automáticamente */ type CampaignEvent = | "click" | "impression" | "conversion" | "lead" | "purchase";

type CampaignEventHandler = on${Capitalize<CampaignEvent>}; // "onClick" | "onImpression" | "onConversion" | "onLead" | "onPurchase"

/** Rutas de API construidas desde los recursos */ type Resource = "campaign" | "user" | "metric" | "report"; type HttpMethod = "get" | "post" | "put" | "delete";

type ApiRoute = /${Resource}s | /${Resource}s/:id; // "/campaigns" | "/campaigns/:id" | "/users" | "/users/:id" | ...

type ApiEndpoint = ${Uppercase<HttpMethod>} ${ApiRoute}; // "GET /campaigns" | "POST /campaigns" | "GET /campaigns/:id" | ...

/** Paths de configuración anidada type-safe */ interface AppConfig { api: { baseUrl: string; timeout: number; retries: number; }; feature: { aiOptimization: boolean; multiChannel: boolean; }; theme: { primaryColor: string; darkMode: boolean; }; }

type NestedPath<T, Prefix extends string = ""> = { [K in keyof T & string]: T[K] extends object ? NestedPath<T[K], ${Prefix}${K}.> : ${Prefix}${K}; }[keyof T & string];

type ConfigPath = NestedPath; // "api.baseUrl" | "api.timeout" | "api.retries" | // "feature.aiOptimization" | "feature.multiChannel" | // "theme.primaryColor" | "theme.darkMode"

/** Acceso type-safe a la config por path */ type GetByPath<T, P extends string> = P extends ${infer K}.${infer Rest} ? K extends keyof T ? GetByPath<T[K], Rest> : never : P extends keyof T ? T[P] : never;

type TimeoutType = GetByPath<AppConfig, "api.timeout">; // number type DarkModeType = GetByPath<AppConfig, "theme.darkMode">; // boolean

// ============================================================ // 5. UTILITY TYPES — Sistema de métricas tipado // ============================================================

/** Métrica de rendimiento de campaña */ interface CampaignMetric { campaignId: string; channel: Channel; date: Date; impressions: number; clicks: number; conversions: number; spend: number; revenue: number; ctr: number; roas: number; }

/** Solo las métricas numéricas (para gráficas) */ type NumericMetrics = { [K in keyof CampaignMetric as CampaignMetric[K] extends number ? K : never]: number; }; // { impressions, clicks, conversions, spend, revenue, ctr, roas }

/** Resumen de métricas: campos requeridos mínimos */ type MetricSummary = Required<Pick<CampaignMetric, "impressions" | "clicks" | "conversions" | "roas">>;

/** Mapa de métricas por canal */ type MetricsByChannel = Record<Channel, NumericMetrics>;

/** Estado del store de métricas */ type MetricStore = { byId: Record<string, CampaignMetric>; byCampaign: Record<string, CampaignMetric[]>; loading: boolean; error: string | null; selectedChannels: Channel[]; };

// ============================================================ // BONUS: Type Guards y Discriminated Unions // ============================================================

/** Estados de una campaña con datos adicionales por estado */ type CampaignState = | { status: "draft"; draftData: { savedAt: Date } } | { status: "active"; activeData: { launchedAt: Date; dailyBudget: number } } | { status: "paused"; pausedData: { reason: string; pausedAt: Date } } | { status: "completed"; completedData: { finalReport: string } };

/** Type guard para campaña activa */ function isActiveCampaign( state: CampaignState ): state is Extract<CampaignState, { status: "active" }> { return state.status === "active"; }

/** Type guard genérico con key check */ function hasProperty<T extends object, K extends PropertyKey>( obj: T, key: K ): obj is T & Record<K, unknown> { return key in obj; }

// Uso en componente React (sin JSX para claridad): function processCampaignState(state: CampaignState) { if (isActiveCampaign(state)) { // TypeScript sabe que state.activeData existe const { dailyBudget } = state.activeData; return Activa — presupuesto diario: ${dailyBudget}€; } if (state.status === "completed") { return Completada — reporte: ${state.completedData.finalReport}; } return Estado: ${state.status}; }

// ============================================================ // BONUS 2: Tipos de Testing // ============================================================

/** Utilidad para verificar igualdad de tipos en tiempo de compilación */ type AssertEqual<T, U> = [T] extends [U] ? [U] extends [T] ? true : false : false;

// Tests de tipos (fallarían en compilación si algo está mal): type _test1 = AssertEqual<MetricSummary["impressions"], number>; // true type _test2 = AssertEqual<AllowedActions<"viewer">, "read">; // true type _test3 = AssertEqual<GetByPath<AppConfig, "api.timeout">, number>; // true type _test4 = AssertEqual<CampaignEventHandler, "onClick" | "onImpression" | "onConversion" | "onLead" | "onPurchase">; // true

export type { ApiResponse, Campaign, CampaignMetric, CampaignState, CampaignEvent, CampaignEventHandler, AppConfig, ConfigPath, Role, Permissions, MetricsByChannel, MetricStore, };

// qué_hace

Enseña a dominar el sistema de tipos avanzados de TypeScript para construir aplicaciones robustas y type-safe.

// cómo_lo_hace

Proporciona ejemplos practicos y patrones reutilizables de genericos, tipos condicionales, mapeados, literales de plantilla y utility types con buenas practicas y errores comunes.

// ejemplo_de_uso

Para desarrolladores TypeScript que necesitan modelar estructuras de datos complejas con garantías de tipo en tiempo de compilación. Ej.: usar tipos mapeados y condicionales para construir un validador genérico que infiera el tipo de respuesta de cada endpoint de tu API.

// plataformas

TypeScriptNode.jsBrowser
Categoría
Web
Tipo
Referencia
Nivel
Avanzado
Licencia
MIT
Seguridad
seguro · riesgo bajo
Versión
1.0.0

// opiniones_de_la_comunidad

Opiniones

Cargando opiniones…

// pase_cultiva_ia

Llévate todo el arsenal con el Pase

Todas las skills, prompts y automatizaciones del catálogo en un único archivo, listas para usar: un pago, acceso de por vida y las novedades que añadamos. Sin suscripción.

Pago único · IVA incluido · pago seguro con Stripe.

Acceso inmediato · si no es lo que esperabas, te devolvemos los 10 €.