<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Tutorial · DacaCode &lt;/&gt;</title><link>https://blog.dacadev.com/tags/tutorial/</link><description>Blog de tecnología, programación y electrónica, para compartir conocimientos, experiencias y tutoriales con este apasionante mundo.</description><generator>Hugo</generator><language>es-CO</language><copyright>Copyright © 2026 DacaDev. All rights reserved.</copyright><lastBuildDate>Wed, 24 Jun 2026 00:00:00 -0500</lastBuildDate><atom:link href="https://blog.dacadev.com/tags/tutorial/index.xml" rel="self" type="application/rss+xml"/><image><url>https://blog.dacadev.com/images/blog-logo.png</url><title>DacaCode &lt;/&gt;</title><link>https://blog.dacadev.com/</link></image><item><title>TypeScript: Depuración de errores y tsconfig.json</title><link>https://blog.dacadev.com/programacion/typescript/depuracion-y-tsconfig/</link><pubDate>Wed, 24 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/depuracion-y-tsconfig/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Configura el compilador de TypeScript con tsconfig.json: strict, noImplicitAny, removeComments, sourceMap y salida única para depurar y compilar mejor.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/debugging-tsconfig/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-tsconfigjson-y-para-qué-sirve"&gt;Qué es tsconfig.json y para qué sirve&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#opciones-recomendadas"&gt;Opciones recomendadas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#sourcemap-depurar-el-código-original"&gt;sourceMap: depurar el código original&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#generar-un-único-archivo-de-salida"&gt;Generar un único archivo de salida&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#depurar-errores-con-eficacia"&gt;Depurar errores con eficacia&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Artículo final de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Consolidaremos la configuración del compilador mediante &lt;code&gt;tsconfig.json&lt;/code&gt; y las opciones que facilitan la depuración y mejoran la calidad del código emitido.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;El archivo &lt;code&gt;tsconfig.json&lt;/code&gt; es el centro de control del compilador: define cómo TypeScript interpreta, verifica y transforma tu proyecto. Una configuración bien afinada no solo previene errores, sino que mejora la experiencia de depuración y la calidad del JavaScript resultante. Cerremos la serie dominando esta pieza. La referencia completa está en la &lt;a href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html"




 target="_blank"
 


&gt;documentación oficial de tsconfig.json&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="qué-es-tsconfigjson-y-para-qué-sirve"&gt;Qué es tsconfig.json y para qué sirve&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;tsconfig.json&lt;/code&gt; declara el comportamiento del compilador para todo el proyecto. Cuando se genera por primera vez, muchas opciones aparecen comentadas, y el valor mostrado en el comentario suele ser el recomendado por defecto.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La presencia de un &lt;code&gt;tsconfig.json&lt;/code&gt; en un directorio marca la raíz de un proyecto TypeScript. Ejecutar &lt;code&gt;tsc&lt;/code&gt; sin argumentos hace que el compilador busque este archivo y compile según sus reglas.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="opciones-recomendadas"&gt;Opciones recomendadas&lt;/h2&gt;
&lt;p&gt;Estas opciones de &lt;code&gt;compilerOptions&lt;/code&gt; aportan el mayor valor en un proyecto profesional:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strict&lt;/code&gt;: activa el conjunto completo de comprobaciones estrictas. Es la opción que más errores previene.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;noImplicitAny&lt;/code&gt;: prohíbe que TypeScript asigne &lt;code&gt;any&lt;/code&gt; de forma implícita cuando no puede inferir un tipo, obligándote a ser explícito.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;removeComments&lt;/code&gt;: elimina los comentarios del JavaScript compilado, produciendo una salida más limpia.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sourceMap&lt;/code&gt;: genera &lt;em&gt;source maps&lt;/em&gt; que enlazan el JavaScript emitido con tu código TypeScript original.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;compilerOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;strict&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;noImplicitAny&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;removeComments&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;sourceMap&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;es2015&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;module&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;commonjs&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;outDir&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;dist&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;include&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;src&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;strict&lt;/code&gt; es en realidad un &lt;em&gt;paraguas&lt;/em&gt; que activa varias comprobaciones, entre ellas &lt;code&gt;noImplicitAny&lt;/code&gt;, &lt;code&gt;strictNullChecks&lt;/code&gt; y &lt;code&gt;strictFunctionTypes&lt;/code&gt;. Habilitarlo desde el primer commit evita una migración costosa cuando el proyecto ya acumuló tipos implícitos.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="sourcemap-depurar-el-código-original"&gt;sourceMap: depurar el código original&lt;/h2&gt;
&lt;p&gt;Sin &lt;em&gt;source maps&lt;/em&gt;, cuando depuras en el navegador o en Node solo ves el JavaScript transpilado, que puede diferir notablemente de tu TypeScript. Con &lt;code&gt;sourceMap: true&lt;/code&gt;, el compilador genera archivos &lt;code&gt;.js.map&lt;/code&gt; que permiten al depurador mostrar tu código fuente original, colocar &lt;em&gt;breakpoints&lt;/em&gt; en él e inspeccionar variables con sus nombres reales.&lt;/p&gt;
&lt;p&gt;Esta opción es la diferencia entre depurar el código que escribiste y depurar el código que la máquina generó.&lt;/p&gt;
&lt;h2 id="generar-un-único-archivo-de-salida"&gt;Generar un único archivo de salida&lt;/h2&gt;
&lt;p&gt;Para ciertos escenarios —especialmente proyectos de frontend sin un &lt;em&gt;bundler&lt;/em&gt;— resulta útil concatenar toda la salida en un solo archivo JavaScript. Esto se logra con la opción &lt;code&gt;outFile&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;compilerOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;outFile&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;./main.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;sourceMap&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;removeComments&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;outFile&lt;/code&gt; solo funciona con los sistemas de módulos &lt;code&gt;amd&lt;/code&gt; y &lt;code&gt;system&lt;/code&gt;; no es compatible con &lt;code&gt;commonjs&lt;/code&gt; ni &lt;code&gt;esnext&lt;/code&gt;. En proyectos modernos, lo habitual es delegar el empaquetado a herramientas como webpack o esbuild en lugar de usar &lt;code&gt;outFile&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="depurar-errores-con-eficacia"&gt;Depurar errores con eficacia&lt;/h2&gt;
&lt;p&gt;El flujo de depuración en TypeScript combina las opciones anteriores con la lectura disciplinada de los mensajes del compilador:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cada error incluye un &lt;strong&gt;código&lt;/strong&gt; (por ejemplo &lt;code&gt;TS2345&lt;/code&gt;) que puedes buscar para entender su causa raíz.&lt;/li&gt;
&lt;li&gt;Con &lt;code&gt;strict&lt;/code&gt; activo, los errores afloran en compilación, antes de ejecutar el código.&lt;/li&gt;
&lt;li&gt;Con &lt;code&gt;sourceMap&lt;/code&gt;, los errores en tiempo de ejecución apuntan a tu TypeScript original, no al JavaScript emitido.&lt;/li&gt;
&lt;li&gt;El modo observador (&lt;code&gt;tsc --watch&lt;/code&gt;) reporta los errores de forma incremental mientras escribes.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[Código TS] --&gt; B[tsc con strict]
 B -- error de tipo --&gt; C[Mensaje TSxxxx&lt;br/&gt;en compilación]
 B -- ok --&gt; D[JS + sourceMap]
 D --&gt; E[Runtime]
 E -- error --&gt; F[Stack trace sobre TS&lt;br/&gt;gracias al sourceMap]
&lt;/pre&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;tsconfig.json&lt;/code&gt; es la herramienta que transforma TypeScript de un transpilador genérico en un compilador afinado a tu proyecto. Activar &lt;code&gt;strict&lt;/code&gt; y &lt;code&gt;noImplicitAny&lt;/code&gt; maximiza la detección temprana de errores; &lt;code&gt;sourceMap&lt;/code&gt; hace que la depuración opere sobre tu código real; y &lt;code&gt;removeComments&lt;/code&gt; pule la salida. Dominar estas opciones cierra el ciclo: del tipado en el editor a la depuración en producción.&lt;/p&gt;
&lt;p&gt;Con esto concluye la serie sobre TypeScript. Has recorrido desde la instalación y los tipos básicos hasta los genéricos, los decoradores y la configuración del compilador: el conjunto de herramientas necesario para construir aplicaciones robustas y mantenibles con tipado estático.&lt;/p&gt;</content:encoded></item><item><title>TypeScript: Namespaces, módulos e importaciones</title><link>https://blog.dacadev.com/programacion/typescript/namespaces-y-modulos/</link><pubDate>Tue, 23 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/namespaces-y-modulos/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Organiza tu código en TypeScript con namespaces y módulos ES: exportaciones nombradas, import, alias, export default y archivos barrel con index.ts.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/namespaces-modules/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#namespaces"&gt;Namespaces&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#módulos-export-e-import"&gt;Módulos: export e import&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#archivos-barrel-centralizar-exportaciones"&gt;Archivos barrel: centralizar exportaciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#export-alias"&gt;Export alias&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#export-default"&gt;Export default&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#del-código-a-un-bundle"&gt;Del código a un bundle&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Décimo artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Organizaremos el código con namespaces y módulos ES: exportaciones nombradas, &lt;code&gt;import&lt;/code&gt;, alias, &lt;code&gt;export default&lt;/code&gt; y archivos &lt;em&gt;barrel&lt;/em&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;A medida que un proyecto crece, la organización del código deja de ser un detalle estético para convertirse en un factor de mantenibilidad. TypeScript ofrece dos mecanismos para estructurar el código: los &lt;strong&gt;namespaces&lt;/strong&gt; —agrupadores internos— y los &lt;strong&gt;módulos ES&lt;/strong&gt; —el estándar moderno basado en &lt;code&gt;export&lt;/code&gt; e &lt;code&gt;import&lt;/code&gt;. Analicemos cuándo usar cada uno.&lt;/p&gt;
&lt;h2 id="namespaces"&gt;Namespaces&lt;/h2&gt;
&lt;p&gt;Un namespace agrupa funciones, clases y variables relacionadas bajo un identificador común, exponiendo solo lo que marques con &lt;code&gt;export&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;namespace&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Validations&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;validateText&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;text&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;boolean&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;text&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;length&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;validateDate&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;myDate&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Date&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;boolean&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;!&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;isNaN&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;myDate&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;valueOf&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Validations&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;validateText&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;hola mundo&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Solo los miembros exportados (&lt;code&gt;validateText&lt;/code&gt;, &lt;code&gt;validateDate&lt;/code&gt;) son accesibles desde fuera mediante la notación &lt;code&gt;Namespace.miembro&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los namespaces se usan cada vez menos en el desarrollo de aplicaciones, donde los módulos ES son el estándar. Sin embargo, siguen presentes como base interna de muchos frameworks y de archivos de definición de tipos (&lt;code&gt;.d.ts&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="módulos-export-e-import"&gt;Módulos: export e import&lt;/h2&gt;
&lt;p&gt;Los módulos son el mecanismo recomendado. Cada archivo es un módulo y expone su API con &lt;code&gt;export&lt;/code&gt;; otros archivos la consumen con &lt;code&gt;import&lt;/code&gt;. Para exportar, antepón &lt;code&gt;export&lt;/code&gt; a la declaración:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// classes/Heros.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;powerID&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Y para consumirla, usa &lt;code&gt;import&lt;/code&gt; con desestructuración de los miembros nombrados:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// index.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; } &lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;./classes/Heros&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;spiderman&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Spiderman&amp;#39;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;23&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="archivos-barrel-centralizar-exportaciones"&gt;Archivos barrel: centralizar exportaciones&lt;/h2&gt;
&lt;p&gt;Cuando una carpeta agrupa varios módulos relacionados, importarlos uno a uno desde rutas distintas se vuelve tedioso. Un archivo &lt;em&gt;barrel&lt;/em&gt; —convencionalmente un &lt;code&gt;index.ts&lt;/code&gt; dentro de la carpeta— reexporta todo desde un único punto de entrada:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// interfaces/index.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; } &lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;./hero&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;Villain&lt;/span&gt; } &lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;./villain&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Esto permite importar múltiples miembros refiriéndote solo a la carpeta, lo que simplifica las rutas y desacopla a los consumidores de la estructura interna:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Villain&lt;/span&gt; } &lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;./interfaces&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre class="mermaid"&gt;flowchart LR
 H[hero.ts] --&gt; I[index.ts barrel]
 V[villain.ts] --&gt; I
 I --&gt; C[consumidor: import desde './interfaces']
&lt;/pre&gt;

&lt;h2 id="export-alias"&gt;Export alias&lt;/h2&gt;
&lt;p&gt;Un alias renombra un miembro al importarlo, lo que resuelve colisiones de nombres entre módulos distintos. Se usa la palabra clave &lt;code&gt;as&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt; &lt;span style="color:#c678dd"&gt;as&lt;/span&gt; &lt;span style="color:#e06c75"&gt;poderes&lt;/span&gt; } &lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;./data/powers&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;poderes&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="export-default"&gt;Export default&lt;/h2&gt;
&lt;p&gt;Una exportación por defecto designa el valor principal de un módulo. Se importa sin llaves y puede combinarse con importaciones nombradas en la misma línea:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// data/powers.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;default&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Powers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;/* ... */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;fuerza&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;velocidad&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Powers&lt;/span&gt;, { &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt; &lt;span style="color:#c678dd"&gt;as&lt;/span&gt; &lt;span style="color:#e06c75"&gt;poderes&lt;/span&gt; } &lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;./data/powers&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Powers&lt;/code&gt; corresponde a la exportación por defecto y &lt;code&gt;poderes&lt;/code&gt; a una exportación nombrada renombrada con alias.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Prefiere las exportaciones nombradas frente a &lt;code&gt;export default&lt;/code&gt; en bases de código grandes: facilitan el &lt;em&gt;autocompletado&lt;/em&gt;, el &lt;em&gt;refactoring&lt;/em&gt; automático y mantienen nombres consistentes entre el módulo y sus consumidores.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="del-código-a-un-bundle"&gt;Del código a un bundle&lt;/h2&gt;
&lt;p&gt;Los módulos resuelven la organización en tiempo de desarrollo, pero el navegador necesita servir el resultado de forma eficiente. Empaquetadores como &lt;strong&gt;webpack&lt;/strong&gt; combinan todos los módulos en uno o pocos archivos optimizados, resolviendo el grafo de dependencias que tejen tus &lt;code&gt;import&lt;/code&gt;. TypeScript se integra en este flujo transpilando primero a JavaScript y dejando que el bundler se encargue del empaquetado final.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Estructurar el código es una decisión de arquitectura. Los namespaces agrupan elementos internos y persisten en definiciones de tipos, pero el estándar moderno son los módulos ES con &lt;code&gt;export&lt;/code&gt;/&lt;code&gt;import&lt;/code&gt;. Los archivos &lt;em&gt;barrel&lt;/em&gt; centralizan las exportaciones, los alias resuelven colisiones de nombres y &lt;code&gt;export default&lt;/code&gt; designa el valor principal de un módulo.&lt;/p&gt;
&lt;p&gt;En el artículo final de la serie consolidaremos la configuración del compilador y la &lt;strong&gt;depuración de errores&lt;/strong&gt; mediante &lt;code&gt;tsconfig.json&lt;/code&gt;.&lt;/p&gt;</content:encoded></item><item><title>TypeScript: Decoradores y metaprogramación</title><link>https://blog.dacadev.com/programacion/typescript/decoradores/</link><pubDate>Mon, 22 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/decoradores/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a usar decoradores en TypeScript: decoradores de clase, de fábrica, de método y de propiedad para extender comportamiento con metaprogramación.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/decorators/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#decoradores-de-clase"&gt;Decoradores de clase&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#decoradores-de-fábrica"&gt;Decoradores de fábrica&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#decoradores-de-método"&gt;Decoradores de método&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#decoradores-de-propiedad"&gt;Decoradores de propiedad&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Noveno artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Estudiaremos los decoradores: funciones que se ejecutan en la definición de clases, métodos y propiedades para extender su comportamiento sin modificar su código original.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Un &lt;strong&gt;decorador en TypeScript&lt;/strong&gt; es una función que se ejecuta en tiempo de transpilación y permite expandir la funcionalidad de un objeto —clase, método o propiedad— de forma declarativa. Frameworks como Angular o NestJS apoyan gran parte de su ergonomía en este mecanismo. Analicemos cada variante con ejemplos prácticos. Puedes consultar la referencia completa en la &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.html"




 target="_blank"
 


&gt;documentación oficial de decoradores&lt;/a&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los decoradores se colocan con la sintaxis &lt;code&gt;@nombre&lt;/code&gt; justo antes del elemento a decorar. Por convención se declaran con &lt;code&gt;function&lt;/code&gt; —en lugar de arrow functions— para distinguirlos visualmente de las funciones ordinarias.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="decoradores-de-clase"&gt;Decoradores de clase&lt;/h2&gt;
&lt;p&gt;Un decorador de clase recibe el constructor y se ejecuta &lt;strong&gt;una sola vez&lt;/strong&gt;, en el momento en que se define la clase —no al crear cada instancia:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;printToConsole&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Function&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;@printToConsole&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pokemon&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;publicApi&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;https://pokeapi.co&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Al crear varias instancias, el decorador no vuelve a ejecutarse: su efecto ocurre en la definición, no en la instanciación.&lt;/p&gt;
&lt;h2 id="decoradores-de-fábrica"&gt;Decoradores de fábrica&lt;/h2&gt;
&lt;p&gt;Un decorador de fábrica es una función que &lt;strong&gt;retorna&lt;/strong&gt; el decorador real. Esto permite parametrizar el comportamiento, aceptando argumentos que controlan cómo se aplica:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;printToConsole&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Function&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;printToConsoleConditional&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;print&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Function&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;print&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;?&lt;/span&gt; &lt;span style="color:#e06c75"&gt;printToConsole&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; () &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;@printToConsoleConditional&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pokemon&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;publicApi&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;https://pokeapi.co&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Un patrón habitual es sellar el prototipo para impedir que se alteren sus propiedades en tiempo de ejecución:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;blockPrototype&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;function&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Function&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;Object&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;seal&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;Object&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;seal&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;prototype&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;@blockPrototype&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;@printToConsoleConditional&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pokemon&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Cuando aplicas múltiples decoradores, se ejecutan de forma secuencial &lt;strong&gt;de abajo hacia arriba&lt;/strong&gt;. En el ejemplo anterior, primero corre &lt;code&gt;printToConsoleConditional&lt;/code&gt; y luego &lt;code&gt;blockPrototype&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="decoradores-de-método"&gt;Decoradores de método&lt;/h2&gt;
&lt;p&gt;Un decorador de método recibe tres argumentos —el objeto al que pertenece, el nombre del método y su &lt;code&gt;PropertyDescriptor&lt;/code&gt;— y puede inspeccionar o &lt;strong&gt;reemplazar&lt;/strong&gt; por completo el comportamiento del método. Aquí lo usamos para validar argumentos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;CheckValidPokemonId() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;function&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;target&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;any&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;propertyKey&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;descriptor&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;PropertyDescriptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;originalMethod&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;descriptor&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;descriptor&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;value&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;id&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;||&lt;/span&gt; &lt;span style="color:#e06c75"&gt;id&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;error&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;El id del pokemon debe estar entre 1 y 100&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;originalMethod&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pokemon&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;publicApi&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;https://pokeapi.co&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;@CheckValidPokemonId&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;savePokemonToDB&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#98c379"&gt;`Pokemon guardado en la base de datos &lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Al envolver &lt;code&gt;originalMethod&lt;/code&gt;, el decorador intercepta la llamada, valida el &lt;code&gt;id&lt;/code&gt; y solo delega al método original cuando el valor es válido. Este es el fundamento de las validaciones declarativas de muchos frameworks.&lt;/p&gt;
&lt;h2 id="decoradores-de-propiedad"&gt;Decoradores de propiedad&lt;/h2&gt;
&lt;p&gt;Un decorador de propiedad recibe el objeto y el nombre de la propiedad, y puede alterar cómo se lee y escribe. Es útil para controlar el acceso a datos —recordando que JavaScript no tiene propiedades verdaderamente privadas en runtime:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;readOnly&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;isWriteable&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Function&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;function&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;target&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;any&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;propertyKey&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;descriptor&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;PropertyDescriptor&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;get&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Daca code&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;set&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;val&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;Object&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;defineProperty&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;propertyKey&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;val&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;writable&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;!&lt;/span&gt;&lt;span style="color:#e06c75"&gt;isWriteable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;enumerable&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;descriptor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pokemon&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;@readOnly&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;publicApi&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;https://pokeapi.co&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El decorador define un &lt;code&gt;get&lt;/code&gt;/&lt;code&gt;set&lt;/code&gt; personalizado que gobierna por completo el acceso a &lt;code&gt;publicApi&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Los decoradores aportan metaprogramación declarativa a TypeScript: el decorador de clase actúa sobre el constructor una única vez, el de fábrica parametriza el comportamiento, el de método intercepta y reemplaza llamadas, y el de propiedad controla la lectura y escritura. Componerlos en cadena —respetando su orden de ejecución— es lo que habilita las APIs elegantes de frameworks modernos.&lt;/p&gt;
&lt;p&gt;En el próximo artículo organizaremos el código con &lt;strong&gt;namespaces y módulos&lt;/strong&gt;: &lt;code&gt;export&lt;/code&gt;, &lt;code&gt;import&lt;/code&gt;, alias y exportaciones por defecto.&lt;/p&gt;</content:encoded></item><item><title>TypeScript: Genéricos y código reutilizable</title><link>https://blog.dacadev.com/programacion/typescript/genericos/</link><pubDate>Sat, 20 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/genericos/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a usar genéricos en TypeScript para escribir funciones y clases reutilizables que preservan la seguridad de tipos con parámetros de tipo dinámicos.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/generics/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#funciones-genéricas"&gt;Funciones genéricas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#por-qué-no-basta-con-any"&gt;Por qué no basta con any&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#clases-genéricas"&gt;Clases genéricas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#restringir-genéricos-con-extends"&gt;Restringir genéricos con extends&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Séptimo artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Exploraremos los genéricos: funciones y clases que operan sobre tipos dinámicos sin renunciar a la verificación estática.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Los &lt;strong&gt;genéricos en TypeScript&lt;/strong&gt; resuelven una tensión recurrente: escribir código reutilizable que funcione con cualquier tipo, pero sin caer en &lt;code&gt;any&lt;/code&gt; y perder toda la seguridad. Un genérico introduce un &lt;em&gt;parámetro de tipo&lt;/em&gt; —una variable que representa un tipo aún por determinar— que se resuelve en el momento de uso. Analicemos cómo aplicarlos.&lt;/p&gt;
&lt;h2 id="funciones-genéricas"&gt;Funciones genéricas&lt;/h2&gt;
&lt;p&gt;Una función genérica declara su parámetro de tipo con la sintaxis &lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt; antes de la lista de parámetros. &lt;code&gt;T&lt;/code&gt; representa el tipo que recibirá, y la función puede usarlo para tipar argumentos y retorno:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Función tradicional
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;genericFunction&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt;&amp;gt;(&lt;span style="color:#e06c75"&gt;argumento&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;T&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;argumento&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Arrow function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;export&lt;/span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;genericArrowFunction&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt;&amp;gt;(&lt;span style="color:#e06c75"&gt;argumento&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;T&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;argumento&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La función anterior retorna exactamente el mismo tipo que recibe. Si la invocas con un &lt;code&gt;string&lt;/code&gt;, TypeScript sabe que el retorno es &lt;code&gt;string&lt;/code&gt;; si la invocas con un &lt;code&gt;number&lt;/code&gt;, el retorno es &lt;code&gt;number&lt;/code&gt;. Esto es lo que distingue a un genérico de &lt;code&gt;any&lt;/code&gt;: &lt;strong&gt;la relación entre entrada y salida se preserva&lt;/strong&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;T&lt;/code&gt; es el nombre convencional, pero es arbitrario. Para múltiples parámetros suelen usarse &lt;code&gt;T&lt;/code&gt;, &lt;code&gt;U&lt;/code&gt;, &lt;code&gt;K&lt;/code&gt;, &lt;code&gt;V&lt;/code&gt;, o nombres descriptivos como &lt;code&gt;TItem&lt;/code&gt; cuando aportan claridad.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="por-qué-no-basta-con-any"&gt;Por qué no basta con any&lt;/h2&gt;
&lt;p&gt;Comparemos las dos aproximaciones para entender el valor de los genéricos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Con any: se pierde la información de tipo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;identityAny&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arg&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;any&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;any&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;identityAny&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;hola&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// a es any → sin autocompletado ni verificación
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Con genéricos: el tipo se conserva
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;identity&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt;&amp;gt;(&lt;span style="color:#e06c75"&gt;arg&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;T&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;identity&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;hola&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// b es string → seguridad completa
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Con &lt;code&gt;any&lt;/code&gt;, el resultado pierde todo su tipo y el typechecker deja de ayudar. Con un genérico, la firma encadena el tipo de entrada con el de salida.&lt;/p&gt;
&lt;h2 id="clases-genéricas"&gt;Clases genéricas&lt;/h2&gt;
&lt;p&gt;Las clases también admiten parámetros de tipo, lo que permite construir estructuras de datos reutilizables y type-safe. El parámetro se declara junto al nombre de la clase y queda disponible en todos sus miembros:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;MyMap&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;K&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;V&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;initialKey&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;K&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;initialValue&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;V&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;get&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;key&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;K&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;V&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;set&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;key&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;K&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;V&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;static&lt;/span&gt; &lt;span style="color:#c678dd"&gt;of&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;K&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;V&lt;/span&gt;&amp;gt;(&lt;span style="color:#e06c75"&gt;k&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;K&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;v&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;V&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;MyMap&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;K&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;V&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Al instanciarla, los tipos pueden indicarse explícitamente o inferirse de los argumentos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;MyMap&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;number&lt;/span&gt;&amp;gt;(&lt;span style="color:#98c379"&gt;&amp;#39;k&amp;#39;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// MyMap&amp;lt;string, number&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;MyMap&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;k&amp;#39;&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// MyMap&amp;lt;string, boolean&amp;gt; (inferido)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;.&lt;span style="color:#c678dd"&gt;get&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;k&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;b&lt;/span&gt;.&lt;span style="color:#c678dd"&gt;set&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;k&amp;#39;&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre class="mermaid"&gt;flowchart LR
 G["MyMap&amp;lt;K, V&amp;gt;"] --&gt; A["MyMap&amp;lt;string, number&amp;gt;"]
 G --&gt; B["MyMap&amp;lt;string, boolean&amp;gt;"]
 G --&gt; C["MyMap&amp;lt;number, Hero&amp;gt;"]
&lt;/pre&gt;

&lt;p&gt;Una sola definición genérica genera tantas variantes type-safe como combinaciones de tipos uses.&lt;/p&gt;
&lt;h2 id="restringir-genéricos-con-extends"&gt;Restringir genéricos con extends&lt;/h2&gt;
&lt;p&gt;A veces un genérico no debe aceptar cualquier tipo, sino solo aquellos que cumplan cierta forma. La cláusula &lt;code&gt;extends&lt;/code&gt; impone esa restricción y, a la vez, habilita el acceso seguro a los miembros garantizados:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;getLength&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt; &lt;span style="color:#e06c75"&gt;extends&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;length&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; }&amp;gt;(&lt;span style="color:#e06c75"&gt;item&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;item&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;length&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;getLength&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;hola&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// OK: string tiene length
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;getLength&lt;/span&gt;([&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;]) &lt;span style="color:#7f848e"&gt;// OK: array tiene length
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;getLength&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;42&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// Error: number no tiene &amp;#39;length&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;T extends { length: number }&lt;/code&gt; restringe &lt;code&gt;T&lt;/code&gt; a tipos que posean una propiedad &lt;code&gt;length&lt;/code&gt;, permitiendo usarla con seguridad dentro de la función.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Los genéricos son la herramienta que permite escribir código verdaderamente reutilizable sin sacrificar la verificación de tipos. Las funciones genéricas encadenan el tipo de entrada con el de salida, las clases genéricas habilitan estructuras de datos type-safe, y las restricciones con &lt;code&gt;extends&lt;/code&gt; acotan los tipos aceptados mientras exponen sus miembros de forma segura.&lt;/p&gt;
&lt;p&gt;En el próximo artículo abordaremos los &lt;strong&gt;tipos avanzados&lt;/strong&gt;: subtipos, supertipos, varianza y la jerarquía completa del sistema de tipos.&lt;/p&gt;</content:encoded></item><item><title>TypeScript: Clases, herencia y patrones de diseño</title><link>https://blog.dacadev.com/programacion/typescript/clases-e-interfaces/</link><pubDate>Fri, 19 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/clases-e-interfaces/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina las clases en TypeScript: herencia, modificadores public/protected/private, clases abstractas, getters/setters, estáticos y patrones Factory y Builder.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/classes-inheritance/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#clases-y-herencia"&gt;Clases y herencia&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#modificadores-de-acceso"&gt;Modificadores de acceso&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#clases-abstractas"&gt;Clases abstractas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#super-invocar-a-la-clase-padre"&gt;super: invocar a la clase padre&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#getters-y-setters"&gt;Getters y setters&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#miembros-estáticos"&gt;Miembros estáticos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#this-como-tipo-de-retorno"&gt;this como tipo de retorno&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipado-estructural"&gt;Tipado estructural&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#constructor-privado"&gt;Constructor privado&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#patrones-de-diseño-habilitados"&gt;Patrones de diseño habilitados&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#factory-pattern"&gt;Factory Pattern&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#builder-pattern"&gt;Builder Pattern&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Sexto artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Recorreremos las clases: herencia, modificadores de acceso, clases abstractas, &lt;code&gt;super&lt;/code&gt;, getters/setters, miembros estáticos, tipado estructural y los patrones de diseño que habilitan.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Las &lt;strong&gt;clases en TypeScript&lt;/strong&gt; parten de la sintaxis de JavaScript y la enriquecen con modificadores de acceso, clases abstractas y tipado estructural. El resultado es un modelo de orientación a objetos cercano al de lenguajes como C++ o Java, pero que compila a JavaScript estándar. Analicemos sus capacidades.&lt;/p&gt;
&lt;h2 id="clases-y-herencia"&gt;Clases y herencia&lt;/h2&gt;
&lt;p&gt;La declaración usa &lt;code&gt;class&lt;/code&gt; y la herencia se establece con &lt;code&gt;extends&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Piece&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;King&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Piece&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Queen&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Piece&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Bishop&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Piece&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podemos restringir los atributos a valores concretos combinando clases con tipos literales:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Color&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Black&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;White&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;File&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;B&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;C&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;D&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;E&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;F&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;G&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;H&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Rank&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;3&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;4&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;5&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;6&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;7&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#d19a66"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Position&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;file&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;File&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;rank&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Rank&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Declarar los parámetros del constructor con un modificador (&lt;code&gt;private file: File&lt;/code&gt;) es un atajo: TypeScript crea y asigna la propiedad automáticamente, evitando el habitual &lt;code&gt;this.file = file&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="modificadores-de-acceso"&gt;Modificadores de acceso&lt;/h2&gt;
&lt;p&gt;TypeScript define tres niveles de visibilidad para atributos y métodos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;public&lt;/code&gt;: accesible desde cualquier lugar. Es el nivel por defecto.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;protected&lt;/code&gt;: accesible desde la propia clase y sus subclases.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;private&lt;/code&gt;: accesible únicamente desde la propia clase.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;team&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;realName?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;bio() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; &lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;team&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;bioInterno() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; &lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;team&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;private&lt;/code&gt; y &lt;code&gt;protected&lt;/code&gt; solo aplican en tiempo de compilación. El JavaScript emitido no impide el acceso en runtime; para privacidad real en ejecución usa los campos privados nativos de JavaScript (&lt;code&gt;#campo&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="clases-abstractas"&gt;Clases abstractas&lt;/h2&gt;
&lt;p&gt;Una clase &lt;code&gt;abstract&lt;/code&gt; define una plantilla que no puede instanciarse, pero sirve de esqueleto para sus subclases. Puede declarar miembros concretos y miembros &lt;code&gt;abstract&lt;/code&gt; que las subclases están obligadas a implementar:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;abstract&lt;/span&gt; &lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Mutante&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Mutante&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;saveWorld() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Mundo salvado&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Villano&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Mutante&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;conquistWorld() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Mundo conquistado&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;wolverine&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Wolverine&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;Logan&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;magneto&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Villano&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Magneto&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;Magnus&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Una ventaja adicional: una función puede aceptar cualquier objeto que herede de la clase abstracta, lo que habilita el polimorfismo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;printName&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;character&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Mutante&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;character&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;printName&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;wolverine&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;printName&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;magneto&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="super-invocar-a-la-clase-padre"&gt;super: invocar a la clase padre&lt;/h2&gt;
&lt;p&gt;Cuando una subclase sobrescribe un método del padre, puede invocar la versión original con &lt;code&gt;super.metodo()&lt;/code&gt;. Si la subclase define un constructor, &lt;strong&gt;debe&lt;/strong&gt; llamar a &lt;code&gt;super()&lt;/code&gt; para inicializar correctamente la cadena de herencia:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;isMutant&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;super&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;getFullNameDesdeXmen() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;super&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;getFullName&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="getters-y-setters"&gt;Getters y setters&lt;/h2&gt;
&lt;p&gt;Los &lt;em&gt;accessors&lt;/em&gt; exponen métodos que se comportan sintácticamente como atributos, facilitando la lectura y asignación controladas:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;get&lt;/span&gt; &lt;span style="color:#e06c75"&gt;fullName() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; - &lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;set&lt;/span&gt; &lt;span style="color:#e06c75"&gt;fullName&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;realName&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;wolverine&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Wolverine&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;Logan&amp;#39;&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;wolverine&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;fullName&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// se lee como atributo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;wolverine&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;fullName&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// se asigna como atributo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="miembros-estáticos"&gt;Miembros estáticos&lt;/h2&gt;
&lt;p&gt;Los miembros &lt;code&gt;static&lt;/code&gt; pertenecen a la clase, no a sus instancias:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;static&lt;/span&gt; &lt;span style="color:#e06c75"&gt;avgAge&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;35&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;static&lt;/span&gt; &lt;span style="color:#e06c75"&gt;getAvgAge() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;avgAge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;avgAge&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// se accede vía la clase
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="this-como-tipo-de-retorno"&gt;this como tipo de retorno&lt;/h2&gt;
&lt;p&gt;Cuando un método retorna la propia instancia, su tipo de retorno es &lt;code&gt;this&lt;/code&gt;. Esto es la base del encadenamiento de métodos (&lt;em&gt;method chaining&lt;/em&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Set&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;add&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="tipado-estructural"&gt;Tipado estructural&lt;/h2&gt;
&lt;p&gt;TypeScript verifica las clases por &lt;strong&gt;estructura&lt;/strong&gt;, no por nombre. Dos tipos compatibles en forma son intercambiables, con una salvedad: los miembros &lt;code&gt;private&lt;/code&gt; rompen la compatibilidad estructural:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;x&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;f&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;A&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;f&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt;()) &lt;span style="color:#7f848e"&gt;// OK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;f&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt;()) &lt;span style="color:#7f848e"&gt;// OK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;f&lt;/span&gt;({ &lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;1&lt;/span&gt; }) &lt;span style="color:#7f848e"&gt;// Error TS2345: &amp;#39;x&amp;#39; es private en &amp;#39;A&amp;#39; pero no en &amp;#39;{x: number}&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="constructor-privado"&gt;Constructor privado&lt;/h2&gt;
&lt;p&gt;Un constructor &lt;code&gt;private&lt;/code&gt; impide instanciar la clase desde fuera, lo que permite controlar su creación. Es la base del patrón &lt;em&gt;singleton&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#c678dd"&gt;static&lt;/span&gt; &lt;span style="color:#e06c75"&gt;instance&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Apocalipsis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#c678dd"&gt;constructor&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;static&lt;/span&gt; &lt;span style="color:#e06c75"&gt;getInstance&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#56b6c2"&gt;!&lt;/span&gt;&lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;instance&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;instance&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Soy Apocalipsis... el único&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;instance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;apocalipsis&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Apocalipsis&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;getInstance&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="patrones-de-diseño-habilitados"&gt;Patrones de diseño habilitados&lt;/h2&gt;
&lt;h3 id="factory-pattern"&gt;Factory Pattern&lt;/h3&gt;
&lt;p&gt;Centraliza la creación de objetos detrás de una función que decide la clase concreta:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Shoe&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;purpose&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;BalletFlat&lt;/span&gt; &lt;span style="color:#c678dd"&gt;implements&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Shoe&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;purpose&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;dancing&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Boot&lt;/span&gt; &lt;span style="color:#c678dd"&gt;implements&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Shoe&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;purpose&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;woodcutting&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Sneaker&lt;/span&gt; &lt;span style="color:#c678dd"&gt;implements&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Shoe&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;purpose&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;walking&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Shoe&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;create&lt;/span&gt;(&lt;span style="color:#c678dd"&gt;type&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;balletFlat&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;boot&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;sneaker&amp;#39;&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Shoe&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;switch&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;type&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;case&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;balletFlat&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;BalletFlat&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;case&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;boot&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Boot&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;case&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;sneaker&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Sneaker&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="builder-pattern"&gt;Builder Pattern&lt;/h3&gt;
&lt;p&gt;Construye un objeto paso a paso mediante métodos que retornan &lt;code&gt;this&lt;/code&gt;, habilitando una API fluida:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RequestBuilder&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;data&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;object&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;method&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;get&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;post&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;private&lt;/span&gt; &lt;span style="color:#e06c75"&gt;url&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;setMethod&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;method&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;get&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;post&amp;#39;&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;method&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;setData&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;data&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;object&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;data&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;setURL&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;url&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;url&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;url&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;send() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RequestBuilder&lt;/span&gt;().&lt;span style="color:#e06c75"&gt;setURL&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;/api&amp;#39;&lt;/span&gt;).&lt;span style="color:#e06c75"&gt;setMethod&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;post&amp;#39;&lt;/span&gt;).&lt;span style="color:#e06c75"&gt;setData&lt;/span&gt;({}).&lt;span style="color:#e06c75"&gt;send&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Las clases de TypeScript ofrecen un modelo de orientación a objetos completo: herencia, modificadores de acceso, clases abstractas para polimorfismo, accessors, miembros estáticos y un tipado estructural con la salvedad de los miembros privados. Estas piezas son el fundamento de patrones de diseño como Factory, Builder y Singleton.&lt;/p&gt;
&lt;p&gt;En el siguiente artículo abordaremos los &lt;strong&gt;genéricos&lt;/strong&gt;, la herramienta para escribir código reutilizable sin sacrificar la seguridad de tipos.&lt;/p&gt;</content:encoded></item><item><title>Estilos CSS: Animaciones con @keyframes</title><link>https://blog.dacadev.com/programacion/estilos-css/animaciones-keyframes/</link><pubDate>Thu, 18 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/animaciones-keyframes/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina las animaciones en CSS con @keyframes: la propiedad animation, iteraciones, direction, fill-mode, play-state, accesibilidad y rendimiento, con ejemplos en vivo.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/09-animaciones-keyframes-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#transición-vs-animación"&gt;Transición vs. animación&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-regla-keyframes"&gt;La regla @keyframes&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#múltiples-pasos-con-porcentajes"&gt;Múltiples pasos con porcentajes&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-propiedad-animation-y-sus-subpropiedades"&gt;La propiedad animation y sus subpropiedades&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#iteration-count-y-direction"&gt;iteration-count y direction&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#fill-mode-el-estado-antes-y-después"&gt;fill-mode: el estado antes y después&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#play-state-y-delay"&gt;play-state y delay&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#encadenar-varias-animaciones"&gt;Encadenar varias animaciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#accesibilidad-respeta-prefers-reduced-motion"&gt;Accesibilidad: respeta prefers-reduced-motion&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#rendimiento-anima-en-la-capa-de-composición"&gt;Rendimiento: anima en la capa de composición&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Una transición anima el salto entre dos estados; pero cuando necesitas movimiento continuo, varios pasos intermedios o una secuencia que se repite —un spinner de carga, un latido, un texto que aparece— necesitas algo más expresivo. Ahí entran las &lt;strong&gt;animaciones con &lt;code&gt;@keyframes&lt;/code&gt;&lt;/strong&gt;, el sistema de CSS para describir secuencias de movimiento complejas de forma declarativa, sin una sola línea de JavaScript.&lt;/p&gt;
&lt;p&gt;Esta entrega extiende la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;, retomando justo donde lo dejaron las transiciones y transformaciones. Cubriremos la regla &lt;code&gt;@keyframes&lt;/code&gt;, todas las subpropiedades de &lt;code&gt;animation&lt;/code&gt;, y las consideraciones de accesibilidad y rendimiento que separan una animación profesional de una que marea al usuario.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Aprenderás a definir secuencias con &lt;code&gt;@keyframes&lt;/code&gt;, a controlarlas con la propiedad &lt;code&gt;animation&lt;/code&gt; y sus ocho subpropiedades, y a respetar las preferencias de movimiento del usuario con &lt;code&gt;prefers-reduced-motion&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="transición-vs-animación"&gt;Transición vs. animación&lt;/h2&gt;
&lt;p&gt;Aunque ambas producen movimiento, resuelven problemas distintos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Una &lt;strong&gt;transición&lt;/strong&gt; (&lt;code&gt;transition&lt;/code&gt;) interpola entre el estado actual y uno nuevo. Necesita un disparador —un &lt;code&gt;:hover&lt;/code&gt;, un cambio de clase— y va de un punto A a un punto B.&lt;/li&gt;
&lt;li&gt;Una &lt;strong&gt;animación&lt;/strong&gt; (&lt;code&gt;animation&lt;/code&gt;) ejecuta una secuencia definida en &lt;code&gt;@keyframes&lt;/code&gt;. No necesita disparador: puede arrancar sola, repetirse indefinidamente y pasar por múltiples estados intermedios.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Regla práctica: usa &lt;code&gt;transition&lt;/code&gt; para cambios de estado provocados por interacción; usa &lt;code&gt;animation&lt;/code&gt; para movimiento autónomo, cíclico o multipaso.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="la-regla-keyframes"&gt;La regla @keyframes&lt;/h2&gt;
&lt;p&gt;Una animación se define en dos partes: la &lt;strong&gt;secuencia&lt;/strong&gt; (con &lt;code&gt;@keyframes&lt;/code&gt;) y su &lt;strong&gt;aplicación&lt;/strong&gt; (con la propiedad &lt;code&gt;animation&lt;/code&gt;). La regla &lt;code&gt;@keyframes&lt;/code&gt; recibe un nombre y describe los estados de la animación en distintos momentos, expresados como porcentajes del 0% al 100% (o con las palabras clave &lt;code&gt;from&lt;/code&gt; y &lt;code&gt;to&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;keyframes&lt;/span&gt; &lt;span style="color:#e06c75"&gt;aparecer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;from&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;opacity&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;translateY&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;to&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;opacity&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;translateY&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;elemento&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;animation&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;aparecer&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.6&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease-out&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;style&gt;
 @keyframes csanim-aparecer {
 from { opacity:0; transform:translateY(1rem); }
 to { opacity:1; transform:translateY(0); }
 }
 .csanim-fade { display:inline-block; background:#2a9da9; color:#fff; padding:.8em 1.4em; border-radius:.4em; animation:csanim-aparecer 1.2s ease-out infinite; }
 &lt;/style&gt;
 &lt;span class="csanim-fade"&gt;Aparezco con fade + desplazamiento&lt;/span&gt;
 &lt;p style="margin:.75rem 0 0;color:#555;"&gt;La secuencia se repite para que puedas observarla.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id="múltiples-pasos-con-porcentajes"&gt;Múltiples pasos con porcentajes&lt;/h3&gt;
&lt;p&gt;El verdadero poder de &lt;code&gt;@keyframes&lt;/code&gt; aparece con pasos intermedios. Cada porcentaje es una &amp;ldquo;foto&amp;rdquo; del estado en ese momento de la animación:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;keyframes&lt;/span&gt; &lt;span style="color:#e06c75"&gt;latido&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;0&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;%&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;scale&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;15&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;%&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;scale&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1.25&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;30&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;%&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;scale&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;45&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;%&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;scale&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1.15&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;60&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;%&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;scale&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;text-align:center;"&gt;
 &lt;style&gt;
 @keyframes csanim-latido {
 0% { transform:scale(1); }
 15% { transform:scale(1.25); }
 30% { transform:scale(1); }
 45% { transform:scale(1.15); }
 60% { transform:scale(1); }
 100% { transform:scale(1); }
 }
 .csanim-heart { display:inline-block; font-size:2.5rem; color:#c0392b; animation:csanim-latido 1.5s ease-in-out infinite; }
 &lt;/style&gt;
 &lt;span class="csanim-heart"&gt;♥&lt;/span&gt;
&lt;/div&gt;
&lt;h2 id="la-propiedad-animation-y-sus-subpropiedades"&gt;La propiedad animation y sus subpropiedades&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;animation&lt;/code&gt; es una propiedad abreviada que agrupa ocho subpropiedades. Conviene conocerlas por separado para tener control fino:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Subpropiedad&lt;/th&gt;
 &lt;th&gt;Función&lt;/th&gt;
 &lt;th&gt;Ejemplo&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-name&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Nombre del &lt;code&gt;@keyframes&lt;/code&gt; a ejecutar&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;aparecer&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-duration&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Duración de un ciclo&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0.6s&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-timing-function&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Curva de progreso&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ease-in-out&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-delay&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Espera antes de iniciar&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;200ms&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-iteration-count&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Número de repeticiones&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;infinite&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-direction&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Sentido de reproducción&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;alternate&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-fill-mode&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Estilos antes/después de animar&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;forwards&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;animation-play-state&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Reproducir o pausar&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;paused&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La forma abreviada las combina en una sola declaración:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;spinner&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;animation&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;girar&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;linear&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;infinite&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;/* name | duration | timing-function | iteration-count */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="iteration-count-y-direction"&gt;iteration-count y direction&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;animation-iteration-count&lt;/code&gt; define cuántas veces se ejecuta (&lt;code&gt;infinite&lt;/code&gt; para un bucle perpetuo). &lt;code&gt;animation-direction&lt;/code&gt; controla el sentido:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;normal&lt;/code&gt; — siempre de 0% a 100%.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reverse&lt;/code&gt; — siempre de 100% a 0%.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternate&lt;/code&gt; — alterna ida y vuelta en cada ciclo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternate-reverse&lt;/code&gt; — igual, pero empezando al revés.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El caso clásico es un &lt;strong&gt;spinner&lt;/strong&gt; de carga, que combina rotación infinita con velocidad constante:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;keyframes&lt;/span&gt; &lt;span style="color:#e06c75"&gt;girar&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;to&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;rotate&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;360&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;); } }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;spinner&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;animation&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;girar&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.8&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;linear&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;infinite&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;text-align:center;"&gt;
 &lt;style&gt;
 @keyframes csanim-girar { to { transform:rotate(360deg); } }
 .csanim-spinner { display:inline-block; width:2.5rem; height:2.5rem; border:.3rem solid #d6eaf0; border-top-color:#2a9da9; border-radius:50%; animation:csanim-girar .8s linear infinite; }
 &lt;/style&gt;
 &lt;span class="csanim-spinner" role="status" aria-label="Cargando"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;h3 id="fill-mode-el-estado-antes-y-después"&gt;fill-mode: el estado antes y después&lt;/h3&gt;
&lt;p&gt;Por defecto, un elemento vuelve a su estilo original en cuanto la animación termina. &lt;code&gt;animation-fill-mode&lt;/code&gt; cambia ese comportamiento:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;none&lt;/code&gt; (por defecto) — no conserva estilos fuera de la ejecución.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;forwards&lt;/code&gt; — mantiene el estado del último keyframe al terminar.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backwards&lt;/code&gt; — aplica el primer keyframe durante el &lt;code&gt;delay&lt;/code&gt;, antes de arrancar.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;both&lt;/code&gt; — combina &lt;code&gt;forwards&lt;/code&gt; y &lt;code&gt;backwards&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;forwards&lt;/code&gt; es esencial cuando quieres que el elemento permanezca en su estado final (por ejemplo, un mensaje que aparece y se queda visible):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;toast&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;animation&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;aparecer&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease-out&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;forwards&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="play-state-y-delay"&gt;play-state y delay&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;animation-play-state&lt;/code&gt; permite pausar (&lt;code&gt;paused&lt;/code&gt;) y reanudar (&lt;code&gt;running&lt;/code&gt;) una animación, típicamente al combinarla con &lt;code&gt;:hover&lt;/code&gt;. Aquí, la barra de progreso se anima sola pero se congela al pasar el cursor:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;keyframes&lt;/span&gt; &lt;span style="color:#e06c75"&gt;cargar&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;from&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;width&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; } &lt;span style="color:#e06c75"&gt;to&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;width&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;; } }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;barra__relleno&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;animation&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;cargar&lt;/span&gt; &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease-in-out&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;infinite&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;barra&lt;/span&gt;:&lt;span style="color:#61afef"&gt;hover&lt;/span&gt; .&lt;span style="color:#e5c07b"&gt;barra__relleno&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;animation-play-state&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;paused&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;style&gt;
 @keyframes csanim-cargar { 0% { width:0; } 100% { width:100%; } }
 .csanim-barra { background:#e5e8e8; border-radius:1rem; overflow:hidden; height:1rem; }
 .csanim-barra__relleno { height:100%; width:0; background:linear-gradient(to right,#2a9da9,#16828d); border-radius:1rem; animation:csanim-cargar 3s ease-in-out infinite; }
 .csanim-barra:hover .csanim-barra__relleno { animation-play-state:paused; }
 &lt;/style&gt;
 &lt;div class="csanim-barra"&gt;&lt;div class="csanim-barra__relleno"&gt;&lt;/div&gt;&lt;/div&gt;
 &lt;p style="margin:.75rem 0 0;color:#555;"&gt;Pasa el cursor sobre la barra para pausar la animación.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="encadenar-varias-animaciones"&gt;Encadenar varias animaciones&lt;/h2&gt;
&lt;p&gt;Puedes aplicar varias animaciones a un mismo elemento separándolas con comas. Cada una mantiene su propia duración, retraso y curva, lo que permite componer comportamientos independientes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;elemento&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;animation&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;aparecer&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease-out&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;flotar&lt;/span&gt; &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease-in-out&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;infinite&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;alternate&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;text-align:center;"&gt;
 &lt;style&gt;
 @keyframes csanim-flotar { from { transform:translateY(0); } to { transform:translateY(-12px); } }
 .csanim-flota { display:inline-block; background:#f39c12; color:#fff; padding:1em 1.6em; border-radius:.5em; box-shadow:0 .4em .8em rgba(0,0,0,.2); animation:csanim-flotar 1.8s ease-in-out infinite alternate; }
 &lt;/style&gt;
 &lt;span class="csanim-flota"&gt;Floto suavemente&lt;/span&gt;
&lt;/div&gt;
&lt;h2 id="accesibilidad-respeta-prefers-reduced-motion"&gt;Accesibilidad: respeta prefers-reduced-motion&lt;/h2&gt;
&lt;p&gt;El movimiento excesivo puede causar mareos o malestar a personas con sensibilidad vestibular. Los sistemas operativos exponen una preferencia de &amp;ldquo;reducir movimiento&amp;rdquo;, y CSS la consulta con la media query &lt;code&gt;prefers-reduced-motion&lt;/code&gt;. Es una responsabilidad profesional desactivar o atenuar las animaciones no esenciales cuando el usuario lo solicita:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;reduce&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;*,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;::&lt;span style="color:#61afef"&gt;before&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;animation-duration&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.01&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;ms&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;animation-iteration-count&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;transition-duration&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.01&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;ms&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Ignorar &lt;code&gt;prefers-reduced-motion&lt;/code&gt; es un fallo de accesibilidad real. Reserva las animaciones llamativas para lo decorativo y asegúrate de que la interfaz siga siendo plenamente funcional cuando el movimiento se reduce.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="rendimiento-anima-en-la-capa-de-composición"&gt;Rendimiento: anima en la capa de composición&lt;/h2&gt;
&lt;p&gt;La misma regla de oro de las transiciones aplica aquí: anima propiedades que solo afecten la etapa de &lt;strong&gt;composición&lt;/strong&gt; del navegador —&lt;code&gt;transform&lt;/code&gt; y &lt;code&gt;opacity&lt;/code&gt;— en lugar de propiedades que disparen &lt;em&gt;layout&lt;/em&gt; o &lt;em&gt;paint&lt;/em&gt; (&lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/* ❌ Costoso: recalcula layout en cada frame */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;keyframes&lt;/span&gt; &lt;span style="color:#e06c75"&gt;mover-malo&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;to&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;left&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;200&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;; } }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/* ✅ Eficiente: solo composición, fluido a 60 fps */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;keyframes&lt;/span&gt; &lt;span style="color:#e06c75"&gt;mover-bien&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;to&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;translateX&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;200&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;); } }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Si una animación se ve entrecortada, lo primero que debes revisar es qué propiedades estás animando. Reescribir un &lt;code&gt;left&lt;/code&gt;/&lt;code&gt;top&lt;/code&gt; como &lt;code&gt;transform: translate()&lt;/code&gt; suele eliminar el &lt;em&gt;jank&lt;/em&gt; de inmediato.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Las animaciones con &lt;code&gt;@keyframes&lt;/code&gt; te dan un lenguaje declarativo para describir movimiento complejo: secuencias multipaso, bucles infinitos y comportamientos compuestos, todo en CSS puro. Dominar la propiedad &lt;code&gt;animation&lt;/code&gt; y sus subpropiedades —especialmente &lt;code&gt;fill-mode&lt;/code&gt;, &lt;code&gt;iteration-count&lt;/code&gt; y &lt;code&gt;play-state&lt;/code&gt;— te permite construir spinners, indicadores de carga y microinteracciones pulidas. Y recuerda: anima &lt;code&gt;transform&lt;/code&gt; y &lt;code&gt;opacity&lt;/code&gt;, y respeta siempre &lt;code&gt;prefers-reduced-motion&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Con esta entrega completas el recorrido de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;: desde la cascada y los selectores hasta el layout, el posicionamiento, los fondos, las transformaciones y, ahora, las animaciones. Tienes el repertorio completo para escribir CSS expresivo, accesible y de alto rendimiento.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>TypeScript: Interfaces y contratos de tipos</title><link>https://blog.dacadev.com/programacion/typescript/interfaces/</link><pubDate>Thu, 18 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/interfaces/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina las interfaces en TypeScript: contratos extensibles, herencia con extends, implementación en clases, diferencias con type y declaration merging.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/interfaces/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#bases-definir-y-extender-interfaces"&gt;Bases: definir y extender interfaces&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#estructuras-complejas-interfaces-anidadas"&gt;Estructuras complejas: interfaces anidadas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#métodos-en-la-interfaz"&gt;Métodos en la interfaz&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementar-interfaces-en-clases"&gt;Implementar interfaces en clases&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#interfaces-para-tipar-funciones"&gt;Interfaces para tipar funciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#interfaces-frente-a-alias-de-tipo"&gt;Interfaces frente a alias de tipo&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#1-composición"&gt;1. Composición&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#2-restricción-al-extender"&gt;2. Restricción al extender&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#3-declaration-merging"&gt;3. Declaration merging&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementación-con-readonly-y-múltiples-contratos"&gt;Implementación con readonly y múltiples contratos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Quinto artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Estudiaremos las interfaces como contratos extensibles, su herencia con &lt;code&gt;extends&lt;/code&gt;, su implementación en clases con &lt;code&gt;implements&lt;/code&gt;, y sus diferencias frente a los alias de tipo.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Una &lt;strong&gt;interface&lt;/strong&gt; en TypeScript define la forma que deben cumplir los objetos. A primera vista se parece a un alias de tipo, pero su rasgo distintivo es la &lt;strong&gt;extensibilidad&lt;/strong&gt;: las interfaces están diseñadas para componerse, heredarse y servir como base de contratos más complejos. Analicemos cuándo y cómo usarlas.&lt;/p&gt;
&lt;h2 id="bases-definir-y-extender-interfaces"&gt;Bases: definir y extender interfaces&lt;/h2&gt;
&lt;p&gt;Una interface declara la estructura de un objeto. Con &lt;code&gt;extends&lt;/code&gt;, una interface puede heredar de otra y ampliar su contrato:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;getName&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;?:&lt;/span&gt; () &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Avenger&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;marvel&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;flash&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Barry Allen&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;24&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;super velocidad&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;viajar en el tiempo&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Avenger&lt;/code&gt; hereda todos los miembros de &lt;code&gt;Hero&lt;/code&gt; y añade &lt;code&gt;marvel&lt;/code&gt;. Esta composición es la base del diseño orientado a contratos.&lt;/p&gt;
&lt;h2 id="estructuras-complejas-interfaces-anidadas"&gt;Estructuras complejas: interfaces anidadas&lt;/h2&gt;
&lt;p&gt;Las interfaces pueden referenciarse entre sí para modelar estructuras de datos compuestas:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Client&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;address?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Address&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Address&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;zip&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;city&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;client&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Client&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;address&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;125&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;zip&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;KYD 234&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;city&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Chía&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;client2&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Client&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Melissa&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Client&lt;/code&gt; referencia a &lt;code&gt;Address&lt;/code&gt; como un campo opcional, lo que permite componer entidades de dominio sin acoplarlas en una sola definición monolítica.&lt;/p&gt;
&lt;h2 id="métodos-en-la-interfaz"&gt;Métodos en la interfaz&lt;/h2&gt;
&lt;p&gt;Al igual que los alias de tipo, las interfaces pueden declarar métodos como parte del contrato:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Client&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;address?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Address&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;getFullAddress&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Declarar métodos en una interface es válido, pero implica que el objeto que la cumpla debe implementarlos. En la práctica, cuando un contrato requiere comportamiento, lo más limpio es implementarlo mediante una clase.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="implementar-interfaces-en-clases"&gt;Implementar interfaces en clases&lt;/h2&gt;
&lt;p&gt;Una clase adopta uno o varios contratos con la palabra clave &lt;code&gt;implements&lt;/code&gt;. Esto garantiza, en compilación, que la clase provee todo lo que el contrato exige:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;mutantPower&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Human&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Mutant&lt;/span&gt; &lt;span style="color:#c678dd"&gt;implements&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Xmen&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Human&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;public&lt;/span&gt; &lt;span style="color:#e06c75"&gt;realName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;mutantPower&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Hola mundo&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Mutant&lt;/code&gt; implementa simultáneamente &lt;code&gt;Xmen&lt;/code&gt; y &lt;code&gt;Human&lt;/code&gt;. Si omitiera cualquier miembro requerido, el compilador lo rechazaría.&lt;/p&gt;
&lt;h2 id="interfaces-para-tipar-funciones"&gt;Interfaces para tipar funciones&lt;/h2&gt;
&lt;p&gt;Aunque es poco frecuente, una interface puede describir la firma de una función antes de asignarle una implementación:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;AddTwoNumbers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;addNumbers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;AddTwoNumbers&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;addNumbers&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="interfaces-frente-a-alias-de-tipo"&gt;Interfaces frente a alias de tipo&lt;/h2&gt;
&lt;p&gt;Esta es la decisión de diseño más común. Las tres diferencias clave:&lt;/p&gt;
&lt;h3 id="1-composición"&gt;1. Composición&lt;/h3&gt;
&lt;p&gt;Los alias de tipo componen mediante operaciones de conjuntos (&lt;code&gt;|&lt;/code&gt;, &lt;code&gt;&amp;amp;&lt;/code&gt;); las interfaces componen mediante &lt;code&gt;extends&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Food&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;calories&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;tasty&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Sushi&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Food&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;amp;&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;salty&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FoodI&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;calories&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;tasty&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;SushiI&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FoodI&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;salty&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-restricción-al-extender"&gt;2. Restricción al extender&lt;/h3&gt;
&lt;p&gt;Al extender una interface, no puedes &lt;strong&gt;cambiar&lt;/strong&gt; el tipo de un miembro heredado, solo añadir o restringir de forma compatible. Una incompatibilidad genera error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;good&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;bad&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt; &lt;span style="color:#c678dd"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;good&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;bad&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2430: &amp;#39;B&amp;#39; extiende incorrectamente &amp;#39;A&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-declaration-merging"&gt;3. Declaration merging&lt;/h3&gt;
&lt;p&gt;Varias interfaces con el mismo nombre en el mismo ámbito &lt;strong&gt;se fusionan automáticamente&lt;/strong&gt;; varios alias de tipo con el mismo nombre producen un error de compilación:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;User&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;User&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; } &lt;span style="color:#7f848e"&gt;// se fusiona
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;User&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Ashley&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;30&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;User&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; } &lt;span style="color:#7f848e"&gt;// Error TS2300: identificador duplicado
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;User&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; } &lt;span style="color:#7f848e"&gt;// Error TS2300
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El &lt;em&gt;declaration merging&lt;/em&gt; respeta los tipos existentes: no puedes redefinir un miembro ya declarado con otro tipo.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Q{¿Necesitas extensibilidad,&lt;br/&gt;implements o merging?}
 Q -- Sí --&gt; I[Usa interface]
 Q -- "No (uniones, tuplas, mapeos)" --&gt; T[Usa type]
&lt;/pre&gt;

&lt;h2 id="implementación-con-readonly-y-múltiples-contratos"&gt;Implementación con readonly y múltiples contratos&lt;/h2&gt;
&lt;p&gt;Las interfaces admiten propiedades &lt;code&gt;readonly&lt;/code&gt; y permiten que una clase cumpla varios contratos a la vez:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Animal&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;readonly&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;eat&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;food&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;hours&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;interface&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Feline&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;meow&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Cat&lt;/span&gt; &lt;span style="color:#c678dd"&gt;implements&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Animal&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Feline&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Whiskers&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;eat&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;food&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) { &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;info&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Ate some&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;food&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;hours&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;) { &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;info&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Slept for&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;hours&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;hours&amp;#39;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;meow() {&lt;/span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;info&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Meow&amp;#39;&lt;/span&gt;) }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Las interfaces son el mecanismo de TypeScript para definir contratos extensibles y verificables. Elige una interface cuando necesites herencia con &lt;code&gt;extends&lt;/code&gt;, implementación en clases con &lt;code&gt;implements&lt;/code&gt; o &lt;em&gt;declaration merging&lt;/em&gt;; reserva los alias de tipo para uniones, intersecciones, tuplas y tipos mapeados.&lt;/p&gt;
&lt;p&gt;En el próximo artículo profundizaremos en las &lt;strong&gt;clases&lt;/strong&gt;, la herencia, los modificadores de acceso y los patrones de diseño que habilitan.&lt;/p&gt;</content:encoded></item><item><title>TypeScript: Funciones, parámetros y generadores</title><link>https://blog.dacadev.com/programacion/typescript/funciones/</link><pubDate>Wed, 17 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/funciones/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a tipar funciones en TypeScript: tipos de retorno, parámetros opcionales y por defecto, operador resto, call signatures, generadores e iteradores.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/functions/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#declaración-y-tipado-de-funciones"&gt;Declaración y tipado de funciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#parámetros-opcionales-y-por-defecto"&gt;Parámetros opcionales y por defecto&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#operador-resto-funciones-variádicas"&gt;Operador resto: funciones variádicas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#call-apply-y-bind"&gt;call, apply y bind&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#generadores"&gt;Generadores&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#iteradores"&gt;Iteradores&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#call-signatures"&gt;Call signatures&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Cuarto artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Cubriremos el tipado de funciones: parámetros, tipos de retorno, parámetros opcionales y por defecto, el operador resto, &lt;em&gt;call signatures&lt;/em&gt;, generadores e iteradores.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Las funciones son el núcleo de cualquier base de código, y es justo donde el tipado aporta más valor: una firma bien tipada documenta el contrato de entrada y salida, y convierte cualquier llamada inválida en un error de compilación. Analicemos cómo TypeScript modela las &lt;strong&gt;funciones&lt;/strong&gt; en toda su variedad.&lt;/p&gt;
&lt;h2 id="declaración-y-tipado-de-funciones"&gt;Declaración y tipado de funciones&lt;/h2&gt;
&lt;p&gt;Una función tipada declara el tipo de cada parámetro y, opcionalmente, el tipo de retorno:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;add&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TypeScript admite todas las formas de definir funciones de JavaScript, y a todas les aplica el mismo sistema de tipos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Named function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;greet&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello &amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Function expression
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;greet2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;function&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello &amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Arrow function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;greet3&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello &amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Shorthand arrow function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;greet4&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello &amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El tipado de los parámetros intercepta llamadas inválidas en el sitio exacto del error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;add&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// Error TS2554: se esperaban 2 argumentos, se recibió 1.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;add&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// Error TS2345: &amp;#39;string&amp;#39; no es asignable a &amp;#39;number&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="parámetros-opcionales-y-por-defecto"&gt;Parámetros opcionales y por defecto&lt;/h2&gt;
&lt;p&gt;Un parámetro opcional se marca con &lt;code&gt;?&lt;/code&gt; y debe gestionarse dentro del cuerpo, ya que puede llegar como &lt;code&gt;undefined&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;userId?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;time&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Date&lt;/span&gt;().&lt;span style="color:#e06c75"&gt;toLocaleTimeString&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;time&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;userId&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;||&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Not signed in&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;Page loaded&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;User signed in&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;da763be&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Un parámetro con valor por defecto se vuelve opcional automáticamente, y TypeScript infiere su tipo a partir del valor asignado:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;userId&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Not signed in&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;time&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Date&lt;/span&gt;().&lt;span style="color:#e06c75"&gt;toISOString&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;time&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;userId&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los parámetros opcionales deben ubicarse &lt;strong&gt;después&lt;/strong&gt; de todos los obligatorios, y no pueden combinarse con el operador resto.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;También puedes apoyarte en un &lt;code&gt;type&lt;/code&gt; para estructurar parámetros de configuración:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Context&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;appId?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;userId?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;context&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Context&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {}) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;time&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Date&lt;/span&gt;().&lt;span style="color:#e06c75"&gt;toISOString&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;time&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;context&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;userId&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="operador-resto-funciones-variádicas"&gt;Operador resto: funciones variádicas&lt;/h2&gt;
&lt;p&gt;El operador resto captura un número dinámico de argumentos en un arreglo tipado, lo que produce firmas más legibles que recibir un arreglo explícito:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Recibe un arreglo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;sum&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;numbers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;[])&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;numbers&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;reduce&lt;/span&gt;((&lt;span style="color:#e06c75"&gt;total&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;total&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;sum&lt;/span&gt;([&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;]) &lt;span style="color:#7f848e"&gt;// 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Variádica con operador resto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;sumVariadicSafe&lt;/span&gt;(...&lt;span style="color:#e06c75"&gt;numbers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;[])&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;numbers&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;reduce&lt;/span&gt;((&lt;span style="color:#e06c75"&gt;total&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;total&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;sumVariadicSafe&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="call-apply-y-bind"&gt;call, apply y bind&lt;/h2&gt;
&lt;p&gt;TypeScript respeta los mecanismos clásicos de invocación de JavaScript, aplicando la verificación de tipos a sus argumentos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;add&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;add&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 30
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;add&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;apply&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;, [&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;]) &lt;span style="color:#7f848e"&gt;// 30
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;add&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;call&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 30
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;add&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;bind&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;)() &lt;span style="color:#7f848e"&gt;// 30
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="generadores"&gt;Generadores&lt;/h2&gt;
&lt;p&gt;Los generadores producen valores bajo demanda. Se declaran con un asterisco tras &lt;code&gt;function&lt;/code&gt; y emiten valores con &lt;code&gt;yield&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#e06c75"&gt;createFibonacciGenerator() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;while&lt;/span&gt; (&lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;yield&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ;[&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#e06c75"&gt;b&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;fib&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;createFibonacciGenerator&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;// IterableIterator&amp;lt;number&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fib&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;next&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;// { value: 0, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fib&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;next&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;// { value: 1, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fib&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;next&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;// { value: 1, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fib&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;next&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;// { value: 2, done: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El método &lt;code&gt;next()&lt;/code&gt; extrae el siguiente valor de la secuencia. TypeScript infiere el tipo &lt;code&gt;IterableIterator&amp;lt;number&amp;gt;&lt;/code&gt; a partir de lo que produce &lt;code&gt;yield&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="iteradores"&gt;Iteradores&lt;/h2&gt;
&lt;p&gt;Un iterador se define implementando el método &lt;code&gt;[Symbol.iterator]&lt;/code&gt;. TypeScript es capaz de reconocer la estructura y tiparla correctamente:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;numbers&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Symbol&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;iterator&lt;/span&gt;]() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;yield&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="call-signatures"&gt;Call signatures&lt;/h2&gt;
&lt;p&gt;Una &lt;em&gt;call signature&lt;/em&gt; describe el tipo de una función de forma independiente a su implementación. Para la siguiente función:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;sum&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;su firma de llamada se expresa así:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El tipo genérico &lt;code&gt;Function&lt;/code&gt; es un comodín que no aporta información sobre la firma concreta; las &lt;em&gt;call signatures&lt;/em&gt; permiten tipar funciones con precisión. Además, cuando una función puede retornar varios tipos, cada uno debe tratarse para satisfacer al typechecker:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;area&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;radius&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;radius&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Math&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;PI&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#e06c75"&gt;radius&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;**&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;area&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;!==&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;null&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;info&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;result:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// dentro del guard, a es number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El tipado de funciones convierte cada firma en un contrato verificable: parámetros opcionales y por defecto modelan flexibilidad controlada, el operador resto expresa funciones variádicas con claridad, las &lt;em&gt;call signatures&lt;/em&gt; tipan funciones como ciudadanos de primera clase, y los generadores e iteradores se integran sin fricción en el sistema de tipos.&lt;/p&gt;
&lt;p&gt;En el siguiente artículo abordaremos las &lt;strong&gt;interfaces&lt;/strong&gt;, el mecanismo de TypeScript para definir contratos extensibles.&lt;/p&gt;</content:encoded></item><item><title>Estilos CSS: Modularización y patrones de diseño</title><link>https://blog.dacadev.com/programacion/estilos-css/modularizacion-y-patrones/</link><pubDate>Tue, 16 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/modularizacion-y-patrones/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a organizar CSS a escala: estilos base, componentes modulares, la metodología BEM, clases de utilidad y la documentación con librerías de patrones.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/08-modularizacion-y-patrones-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-la-modularización"&gt;Qué es la modularización&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#estilos-base"&gt;Estilos base&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#componentes-y-bem"&gt;Componentes y BEM&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#posicionamiento-del-componente"&gt;Posicionamiento del componente&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#estado-de-los-componentes"&gt;Estado de los componentes&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#utility-classes"&gt;Utility classes&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#metodologías-de-arquitectura-css"&gt;Metodologías de arquitectura CSS&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#librerías-de-patrones"&gt;Librerías de patrones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En un proyecto pequeño cualquier organización de CSS funciona. El problema aparece al escalar: hojas de estilo de miles de líneas donde tocar una regla rompe tres componentes que parecían no tener relación. La causa casi siempre es la misma: estilos acoplados que se pisan entre sí. La solución es arquitectónica —modularizar— y existen metodologías probadas para lograrlo.&lt;/p&gt;
&lt;p&gt;Esta es la octava y última entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Veremos cómo estructurar estilos en módulos independientes, la metodología &lt;strong&gt;BEM&lt;/strong&gt;, las clases de utilidad y cómo documentar tus componentes con una librería de patrones.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Aprenderás a dividir tus estilos en componentes desacoplados, a nombrar clases con BEM, a usar utility classes con criterio y a mantener una librería de patrones como fuente única de verdad del diseño.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-es-la-modularización"&gt;Qué es la modularización&lt;/h2&gt;
&lt;p&gt;Modularizar CSS consiste en dividir los estilos en archivos donde cada uno representa un &lt;strong&gt;módulo&lt;/strong&gt;: un único componente con todo su estilo encapsulado. Un módulo &lt;code&gt;button.css&lt;/code&gt; contiene todo lo necesario para renderizar un botón y sus variantes, y nada más.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La regla de oro: un módulo no debe interferir con los estilos de otros. Solo se ocupa de su propio componente. Así, modificar un módulo nunca produce efectos colaterales inesperados en el resto de la página.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="estilos-base"&gt;Estilos base&lt;/h2&gt;
&lt;p&gt;Antes de los módulos conviene tener un archivo de &lt;strong&gt;estilos base&lt;/strong&gt;: no es un componente, sino la configuración inicial del documento (reset, tipografía global, &lt;code&gt;box-sizing&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-sizing&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;border-box&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;*,&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;::&lt;span style="color:#61afef"&gt;before&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-sizing&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;inherit&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;body&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-family&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Helvetica&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Arial&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;sans-serif&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Para no reinventar la rueda, paquetes como &lt;a href="https://necolas.github.io/normalize.css/"




 target="_blank"
 


&gt;Normalize.css&lt;/a&gt; homogeneizan las diferencias entre navegadores de forma sensata.&lt;/p&gt;
&lt;h2 id="componentes-y-bem"&gt;Componentes y BEM&lt;/h2&gt;
&lt;p&gt;La idea central de un módulo es que los estilos y modificadores de un componente vivan en un solo lugar. La metodología &lt;strong&gt;BEM&lt;/strong&gt; (&lt;em&gt;Block, Element, Modifier&lt;/em&gt;) propone una convención de nombres que hace explícita la estructura y evita colisiones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Block&lt;/strong&gt; — el componente raíz: &lt;code&gt;.button&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Element&lt;/strong&gt; — una parte del componente, con &lt;code&gt;__&lt;/code&gt;: &lt;code&gt;.button__icon&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modifier&lt;/strong&gt; — una variante, con &lt;code&gt;--&lt;/code&gt;: &lt;code&gt;.button--success&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;button&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;padding&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.8&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;border&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;solid&lt;/span&gt; &lt;span style="color:#d19a66"&gt;#265559&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;border-radius&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.2&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;transparent&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;button--success&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#2f5926&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;border-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#cfe8c9&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;button--danger&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#a92323&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;border-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#e8c9c9&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;button--small&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.8&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;button--large&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1.2&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;button&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;button&amp;#34;&lt;/span&gt;&amp;gt;Normal&amp;lt;/&lt;span style="color:#e06c75"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;button&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;button button--success&amp;#34;&lt;/span&gt;&amp;gt;Éxito&amp;lt;/&lt;span style="color:#e06c75"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;button&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;button button--danger&amp;#34;&lt;/span&gt;&amp;gt;Peligro&amp;lt;/&lt;span style="color:#e06c75"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;button&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;button button--large&amp;#34;&lt;/span&gt;&amp;gt;Grande&amp;lt;/&lt;span style="color:#e06c75"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;display:flex;gap:.75rem;flex-wrap:wrap;align-items:center;"&gt;
 &lt;button type="button" style="padding:.5em .8em;border:1px solid #265559;border-radius:.2em;background:transparent;font-size:1rem;color:#265559;cursor:pointer;"&gt;Normal&lt;/button&gt;
 &lt;button type="button" style="padding:.5em .8em;border:1px solid #cfe8c9;border-radius:.2em;background:#2f5926;font-size:1rem;color:#fff;cursor:pointer;"&gt;Éxito&lt;/button&gt;
 &lt;button type="button" style="padding:.5em .8em;border:1px solid #e8c9c9;border-radius:.2em;background:#a92323;font-size:1rem;color:#fff;cursor:pointer;"&gt;Peligro&lt;/button&gt;
 &lt;button type="button" style="padding:.5em .8em;border:1px solid #265559;border-radius:.2em;background:transparent;font-size:1.2rem;color:#265559;cursor:pointer;"&gt;Grande&lt;/button&gt;
&lt;/div&gt;
&lt;h3 id="posicionamiento-del-componente"&gt;Posicionamiento del componente&lt;/h3&gt;
&lt;p&gt;Por buena práctica, el bloque raíz de un componente debería declarar &lt;code&gt;position: relative&lt;/code&gt;. Así estableces un contexto de posicionamiento controlado para cualquier elemento absoluto interno (un menú desplegable, un badge, un tooltip), sin depender de ancestros externos.&lt;/p&gt;
&lt;h3 id="estado-de-los-componentes"&gt;Estado de los componentes&lt;/h3&gt;
&lt;p&gt;Es común reflejar el estado de un componente con clases, ya sea para estilizarlo o para manipularlo desde JavaScript. La convención recomendada usa verbos o estados con prefijo: &lt;code&gt;is-loading&lt;/code&gt;, &lt;code&gt;has-error&lt;/code&gt;, &lt;code&gt;is-active&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;No mezcles las clases de estado con los modificadores BEM. Evita nombres como &lt;code&gt;block__element--modifier-is-loading&lt;/code&gt;. El estado es una capa transversal y dinámica; mantenlo separado de la variante estática del componente.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="utility-classes"&gt;Utility classes&lt;/h2&gt;
&lt;p&gt;Las &lt;strong&gt;clases de utilidad&lt;/strong&gt; aplican un estilo único y específico. Suelen usar &lt;code&gt;!important&lt;/code&gt; para garantizar que se apliquen por encima de los estilos del componente:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;text-center&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;text-align&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;center&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;float-left&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;float&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;left&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;hidden&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;none&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;clearfix&lt;/span&gt;::&lt;span style="color:#61afef"&gt;before&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;clearfix&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;content&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34; &amp;#34;&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;table&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;clearfix&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;clear&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;both&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Son útiles para ajustes puntuales, pero abusar de ellas reintroduce el acoplamiento que la modularización busca evitar. Úsalas con criterio.&lt;/p&gt;
&lt;h2 id="metodologías-de-arquitectura-css"&gt;Metodologías de arquitectura CSS&lt;/h2&gt;
&lt;p&gt;BEM no es la única opción. Las metodologías más establecidas para organizar CSS a escala son:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OOCSS&lt;/strong&gt; — &lt;em&gt;Object-Oriented CSS&lt;/em&gt;, de Nicole Sullivan: separa estructura de apariencia.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SMACSS&lt;/strong&gt; — &lt;em&gt;Scalable and Modular Architecture for CSS&lt;/em&gt;, de Jonathan Snook: categoriza las reglas en capas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BEM&lt;/strong&gt; — &lt;em&gt;Block, Element, Modifier&lt;/em&gt;, de Yandex: convención de nombres explícita.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ITCSS&lt;/strong&gt; — &lt;em&gt;Inverted Triangle CSS&lt;/em&gt;, de Harry Roberts: organiza por especificidad creciente.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No son excluyentes; muchos equipos combinan ITCSS para la estructura de archivos con BEM para la nomenclatura.&lt;/p&gt;
&lt;h2 id="librerías-de-patrones"&gt;Librerías de patrones&lt;/h2&gt;
&lt;p&gt;En proyectos grandes, los componentes se documentan en una &lt;strong&gt;librería de patrones&lt;/strong&gt; (o &lt;em&gt;style guide&lt;/em&gt;): una web accesible para todo el equipo que muestra cómo se ve y se comporta cada componente. Es la fuente única de verdad del diseño y reduce las inconsistencias.&lt;/p&gt;
&lt;p&gt;Existen generadores de style guides; uno open source muy conocido es &lt;a href="https://kss-node.github.io/kss-node/"




 target="_blank"
 


&gt;KSS&lt;/a&gt;. Documenta los componentes a partir de comentarios estructurados en el propio CSS:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;Buttons
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;Botones disponibles en varios tamaños y colores.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;Markup:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;&amp;lt;button class=&amp;#34;button {{modifier_class}}&amp;#34;&amp;gt;click here&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;.button--success - Botón verde de éxito
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;.button--danger - Botón rojo de peligro
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;.button--large - Botón grande
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;Styleguide Buttons
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;button&lt;/span&gt; { &lt;span style="color:#7f848e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;KSS lee esos comentarios y genera automáticamente una página de documentación con el componente renderizado y todas sus variantes. El bloque incluye un título, una descripción, el &lt;code&gt;Markup&lt;/code&gt; de ejemplo (con el marcador &lt;code&gt;{{modifier_class}}&lt;/code&gt;), la lista de modificadores y una referencia &lt;code&gt;Styleguide&lt;/code&gt; para ubicarlo en la jerarquía.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Mantener la documentación junto al código —en comentarios del propio CSS— reduce el riesgo de que la librería de patrones quede desactualizada respecto a la implementación real.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Escribir CSS que escale es, ante todo, un problema de arquitectura. Modularizar en componentes desacoplados, nombrar con una convención consistente como BEM, reservar las utility classes para ajustes puntuales y documentar todo en una librería de patrones es lo que mantiene una hoja de estilos sana a medida que el proyecto crece.&lt;/p&gt;
&lt;p&gt;Con esta entrega cerramos la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Recorrimos desde los fundamentos de la cascada hasta la arquitectura de estilos a gran escala, pasando por selectores, el modelo de caja, layouts, posicionamiento, fondos y animaciones. Tienes ahora un modelo mental completo para escribir CSS profesional, predecible y mantenible.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Repasa las entregas anteriores para consolidar cada concepto: los fundamentos sostienen los selectores, el modelo de caja sostiene los layouts, y la modularización une todo en un sistema coherente.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>TypeScript: Objetos y tipos personalizados</title><link>https://blog.dacadev.com/programacion/typescript/objetos-y-tipos-personalizados/</link><pubDate>Tue, 16 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/objetos-y-tipos-personalizados/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a tipar objetos literales en TypeScript, definir tipos personalizados con type, usar campos opcionales y métodos, y permitir múltiples tipos con uniones.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/objects-custom-types/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#objetos-literales-y-la-inferencia-estructural"&gt;Objetos literales y la inferencia estructural&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipar-objetos-de-forma-inline"&gt;Tipar objetos de forma inline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipos-personalizados-con-type"&gt;Tipos personalizados con type&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#permitir-múltiples-tipos-con-uniones"&gt;Permitir múltiples tipos con uniones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Tercer artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Diseñaremos la forma de nuestros objetos con tipos personalizados, definiremos campos opcionales y métodos, y permitiremos que una variable acepte múltiples tipos.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Modelar correctamente la estructura de los objetos es donde TypeScript empieza a pagar dividendos en proyectos reales. Un &lt;strong&gt;tipo personalizado&lt;/strong&gt; bien diseñado centraliza la definición de una entidad, propaga su forma por todo el código y convierte cualquier desviación en un error de compilación. Analicemos cómo pasar de objetos literales sueltos a un modelo de tipos mantenible.&lt;/p&gt;
&lt;h2 id="objetos-literales-y-la-inferencia-estructural"&gt;Objetos literales y la inferencia estructural&lt;/h2&gt;
&lt;p&gt;Los objetos literales funcionan igual que en JavaScript, pero TypeScript infiere automáticamente su estructura. Esa inferencia es justamente lo que impide reasignar un objeto con una forma distinta:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;flash&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Barry Allen&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;24&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;super velocidad&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;viajar en el tiempo&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;flash&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name2&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Otro nombre&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Error: el literal solo puede especificar propiedades conocidas;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// &amp;#39;name2&amp;#39; no existe en el tipo inferido y faltan &amp;#39;name&amp;#39;, &amp;#39;age&amp;#39;, &amp;#39;powers&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TypeScript bloquea la reasignación porque el nuevo literal no respeta la forma deducida de &lt;code&gt;flash&lt;/code&gt;. Este comportamiento evita introducir campos accidentales o incompletos.&lt;/p&gt;
&lt;h2 id="tipar-objetos-de-forma-inline"&gt;Tipar objetos de forma inline&lt;/h2&gt;
&lt;p&gt;Podemos declarar explícitamente la forma del objeto usando la misma sintaxis de anotación que venimos aplicando, incluyendo campos opcionales con &lt;code&gt;?&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;flash&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;age?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[] } &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Barry Allen&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;24&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;super velocidad&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;viajar en el tiempo&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;flash&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Clark Kent&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;volar&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;rayo láser&amp;#39;&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;// &amp;#39;age&amp;#39; es opcional, puede omitirse
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La posición de un campo opcional dentro de la anotación es irrelevante. &lt;code&gt;age?&lt;/code&gt; puede ir en medio de la definición sin afectar la validez de los objetos que lo omitan.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;El problema de este enfoque &lt;em&gt;inline&lt;/em&gt; es la duplicación: si dos variables deben compartir la misma forma, hay que repetir la anotación completa en cada una y mantenerlas sincronizadas manualmente. Esto no escala.&lt;/p&gt;
&lt;h2 id="tipos-personalizados-con-type"&gt;Tipos personalizados con type&lt;/h2&gt;
&lt;p&gt;La solución es definir la estructura una sola vez con la palabra clave &lt;code&gt;type&lt;/code&gt; y reutilizarla en todo el código. Esto centraliza el modelo en un único punto de verdad:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;getName&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;?:&lt;/span&gt; () &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;flash&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Barry Allen&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;24&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;super velocidad&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;viajar en el tiempo&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;superman&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Clark Kent&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;30&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;volar&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;rayo láser&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;getName() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;this&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El tipo &lt;code&gt;Hero&lt;/code&gt; declara &lt;code&gt;name&lt;/code&gt; y &lt;code&gt;powers&lt;/code&gt; como obligatorios, &lt;code&gt;age&lt;/code&gt; como opcional y &lt;code&gt;getName&lt;/code&gt; como un &lt;strong&gt;método opcional&lt;/strong&gt; cuya firma es &lt;code&gt;() =&amp;gt; string&lt;/code&gt;. Cualquier objeto anotado con &lt;code&gt;Hero&lt;/code&gt; debe respetar este contrato, y un solo cambio en la definición se propaga a todas las variables que lo usan.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 T[type Hero] --&gt; A[flash: Hero]
 T --&gt; B[superman: Hero]
 T --&gt; C[...otros héroes]
 note["Un cambio en Hero&lt;br/&gt;se propaga a todos"] -.-&gt; T
&lt;/pre&gt;





 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Define un &lt;code&gt;type&lt;/code&gt; para toda entidad que aparezca más de una vez. La regla práctica: si copiarías la anotación inline por segunda vez, conviértela en un tipo personalizado.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="permitir-múltiples-tipos-con-uniones"&gt;Permitir múltiples tipos con uniones&lt;/h2&gt;
&lt;p&gt;Una variable puede aceptar más de un tipo mediante el operador de unión &lt;code&gt;|&lt;/code&gt;. Esto resulta útil para valores que legítimamente cambian de forma según el contexto:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;getName&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;?:&lt;/span&gt; () &lt;span style="color:#56b6c2"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;myCustomVariable&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Hero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;¡Hola mundo!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;myCustomVariable&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;42&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// válido: number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;myCustomVariable&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#7f848e"&gt;// válido: Hero
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Diana&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;powers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;fuerza sobrehumana&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;myCustomVariable&lt;/code&gt; puede contener un &lt;code&gt;Hero&lt;/code&gt;, un &lt;code&gt;string&lt;/code&gt; o un &lt;code&gt;number&lt;/code&gt;. El typechecker permitirá únicamente operaciones válidas para todos los miembros de la unión hasta que acotes el tipo con un &lt;em&gt;type guard&lt;/em&gt; (por ejemplo, &lt;code&gt;typeof&lt;/code&gt; o una comprobación de propiedad).&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Pasar de objetos literales inline a tipos personalizados con &lt;code&gt;type&lt;/code&gt; es el salto que transforma TypeScript de una simple validación a una herramienta de diseño. Un tipo centraliza la forma de una entidad, los campos opcionales modelan la realidad de los datos incompletos, los métodos definen comportamiento esperado y las uniones aportan flexibilidad controlada.&lt;/p&gt;
&lt;p&gt;En el próximo artículo de la serie abordaremos las &lt;strong&gt;funciones&lt;/strong&gt;: anotación de parámetros, tipos de retorno, parámetros opcionales y sobrecargas.&lt;/p&gt;</content:encoded></item><item><title>Estilos CSS: Transiciones, transformaciones y rendimiento</title><link>https://blog.dacadev.com/programacion/estilos-css/transiciones-y-transformaciones/</link><pubDate>Sun, 14 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/transiciones-y-transformaciones/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina las transiciones y transformaciones en CSS: timing functions, las funciones transform (scale, rotate, translate, skew), perspectiva 3D y el pipeline de render.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/07-transiciones-y-transformaciones-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#transiciones"&gt;Transiciones&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#timing-functions"&gt;Timing functions&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#transformaciones"&gt;Transformaciones&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#rotación"&gt;Rotación&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#traslación"&gt;Traslación&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#escala"&gt;Escala&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#inclinación"&gt;Inclinación&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#punto-de-referencia-transform-origin"&gt;Punto de referencia: transform-origin&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#combinar-transformaciones"&gt;Combinar transformaciones&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-pipeline-de-renderizado"&gt;El pipeline de renderizado&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#transformaciones-en-3d"&gt;Transformaciones en 3D&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Las transiciones y transformaciones son la puerta de entrada a las interfaces animadas. Una transición suaviza el cambio entre dos estados; una transformación altera la geometría visual de un elemento sin afectar el layout. Bien aplicadas, mejoran la percepción de calidad y guían la atención del usuario. Mal aplicadas, generan &lt;em&gt;jank&lt;/em&gt; y consumen batería. La diferencia está en entender qué propiedades son baratas de animar y por qué.&lt;/p&gt;
&lt;p&gt;Esta es la séptima entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Cubriremos la propiedad &lt;code&gt;transition&lt;/code&gt; y sus &lt;em&gt;timing functions&lt;/em&gt;, las funciones de &lt;code&gt;transform&lt;/code&gt; en 2D y 3D, y el pipeline de renderizado que explica por qué &lt;code&gt;transform&lt;/code&gt; y &lt;code&gt;opacity&lt;/code&gt; son las propiedades óptimas para animar.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Aprenderás a construir transiciones fluidas con curvas de Bézier, a aplicar y combinar transformaciones, y a entender el pipeline layout → paint → composición para escribir animaciones eficientes.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="transiciones"&gt;Transiciones&lt;/h2&gt;
&lt;p&gt;Una transición interpola el cambio de una propiedad entre su valor inicial y final a lo largo del tiempo. Suele combinarse con pseudo-clases como &lt;code&gt;:hover&lt;/code&gt; o &lt;code&gt;:active&lt;/code&gt;. Se controla con cuatro propiedades:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;transition-property&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;background-color&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt; &lt;span style="color:#e06c75"&gt;transform&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;transition-duration&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;0&lt;/span&gt;.&lt;span style="color:#e5c07b"&gt;3s&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt; &lt;span style="color:#e06c75"&gt;0&lt;/span&gt;.&lt;span style="color:#e5c07b"&gt;6s&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;transition-timing-function&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ease&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt; &lt;span style="color:#e06c75"&gt;linear&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;transition-delay&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;0s&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt; &lt;span style="color:#e06c75"&gt;100ms&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;transition-property&lt;/code&gt;&lt;/strong&gt; — qué propiedades se animan (usa &lt;code&gt;all&lt;/code&gt; para todas).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;transition-duration&lt;/code&gt;&lt;/strong&gt; — cuánto dura la interpolación.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;transition-timing-function&lt;/code&gt;&lt;/strong&gt; — cómo se distribuye el movimiento en el tiempo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;transition-delay&lt;/code&gt;&lt;/strong&gt; — cuánto espera antes de empezar (opcional).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;boton&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transition&lt;/span&gt;: &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease&lt;/span&gt;, &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;ease&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;boton&lt;/span&gt;:&lt;span style="color:#61afef"&gt;hover&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#16828d&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;translateY&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;-3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;style&gt;
 .cstrans { padding:.8em 1.6em; border:0; color:#fff; border-radius:.5em; cursor:pointer; background:#2a9da9; transition:background-color .3s ease, transform .3s ease, box-shadow .3s ease; box-shadow:0 .15em .4em rgba(0,0,0,.2); }
 .cstrans:hover { background:#16828d; transform:translateY(-4px); box-shadow:0 .4em .8em rgba(0,0,0,.3); }
 &lt;/style&gt;
 &lt;button class="cstrans" type="button"&gt;Pasa el cursor sobre mí&lt;/button&gt;
&lt;/div&gt;
&lt;h3 id="timing-functions"&gt;Timing functions&lt;/h3&gt;
&lt;p&gt;La &lt;em&gt;timing function&lt;/em&gt; define cómo se reparte el movimiento en el tiempo. Existen valores predefinidos —&lt;code&gt;linear&lt;/code&gt;, &lt;code&gt;ease&lt;/code&gt;, &lt;code&gt;ease-in&lt;/code&gt;, &lt;code&gt;ease-out&lt;/code&gt;, &lt;code&gt;ease-in-out&lt;/code&gt;— donde el eje X representa el tiempo y el eje Y el progreso del cambio.&lt;/p&gt;
&lt;p&gt;Todas son &lt;strong&gt;curvas de Bézier&lt;/strong&gt;, y puedes definir la tuya con la función &lt;code&gt;cubic-bezier()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;box&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transition&lt;/span&gt;: &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.6&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;cubic-bezier&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0.45&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0.05&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0.55&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0.95&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;También puedes hacer el cambio en pasos discretos con &lt;code&gt;steps()&lt;/code&gt;, útil para animaciones tipo sprite o efectos de &amp;ldquo;tecleo&amp;rdquo;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;box&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transition&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;all&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;s&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;steps&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;3&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Existen editores visuales de curvas de Bézier que te permiten ajustar la animación y copiar el valor exacto. Experimentar con ellos es la forma más rápida de afinar la sensación de una transición.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="transformaciones"&gt;Transformaciones&lt;/h2&gt;
&lt;p&gt;La propiedad &lt;code&gt;transform&lt;/code&gt; altera la geometría visual de un elemento mediante cuatro operaciones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;scale()&lt;/code&gt;&lt;/strong&gt; — escala el tamaño.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;rotate()&lt;/code&gt;&lt;/strong&gt; — rota el elemento.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;translate()&lt;/code&gt;&lt;/strong&gt; — lo desplaza.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;skew()&lt;/code&gt;&lt;/strong&gt; — lo inclina/estira.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Las transformaciones solo alteran la representación visual del elemento, &lt;strong&gt;no su comportamiento en el layout&lt;/strong&gt;. El hueco original que ocupaba se conserva, y los elementos vecinos no se reorganizan.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="rotación"&gt;Rotación&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rotate()&lt;/code&gt; gira el elemento. Los valores positivos giran en sentido horario; los negativos, antihorario.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;giro&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;rotate&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;15&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="traslación"&gt;Traslación&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;translate(x, y)&lt;/code&gt; mueve el elemento en ambos ejes sin afectar el flujo. Los valores positivos lo desplazan a la derecha y hacia abajo.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;mover&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;translate&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;40&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="escala"&gt;Escala&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;scale()&lt;/code&gt; redimensiona: valores entre 0 y 1 encogen, mayores que 1 agrandan.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;crecer&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;scale&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1.3&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="inclinación"&gt;Inclinación&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;skew(x, y)&lt;/code&gt; deforma el elemento inclinándolo respecto a los ejes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;inclinar&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#61afef;font-weight:bold"&gt;skew&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;-12&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;display:flex;gap:1.5rem;flex-wrap:wrap;align-items:center;justify-content:center;"&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:1em;border-radius:.4em;transform:rotate(15deg);display:inline-block;"&gt;rotate&lt;/span&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:1em;border-radius:.4em;transform:translate(0,-8px);display:inline-block;"&gt;translate&lt;/span&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:1em;border-radius:.4em;transform:scale(1.25);display:inline-block;"&gt;scale&lt;/span&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:1em;border-radius:.4em;transform:skew(-12deg);display:inline-block;"&gt;skew&lt;/span&gt;
&lt;/div&gt;
&lt;h3 id="punto-de-referencia-transform-origin"&gt;Punto de referencia: transform-origin&lt;/h3&gt;
&lt;p&gt;Toda transformación se aplica desde un punto de referencia, que por defecto es el centro del elemento. &lt;code&gt;transform-origin&lt;/code&gt; lo reubica:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;giro&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform-origin&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;left&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;center&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* equivale a 0% 50% */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="combinar-transformaciones"&gt;Combinar transformaciones&lt;/h3&gt;
&lt;p&gt;Puedes encadenar varias funciones separándolas por espacios. &lt;strong&gt;Se aplican de derecha a izquierda&lt;/strong&gt;, lo que afecta el resultado final:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;tarjeta&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;rotate&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;15&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;) &lt;span style="color:#e5c07b"&gt;translate&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;20&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="el-pipeline-de-renderizado"&gt;El pipeline de renderizado&lt;/h2&gt;
&lt;p&gt;Para escribir animaciones eficientes hay que entender cómo el navegador dibuja una página. El proceso tiene tres etapas clave:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Layout&lt;/strong&gt; — el navegador calcula las dimensiones y posiciones de todos los elementos. Cualquier cambio de tamaño o posición dispara un recálculo completo (&lt;em&gt;reflow&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paint&lt;/strong&gt; — pinta en memoria los píxeles de cada elemento (colores, bordes, sombras), posiblemente en capas separadas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Composición&lt;/strong&gt; — combina las capas pintadas para mostrarlas en pantalla.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[JS / CSS] --&gt; B[Layout]
 B --&gt; C[Paint]
 C --&gt; D[Composición]
&lt;/pre&gt;

&lt;p&gt;La clave del rendimiento: algunas propiedades, como &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/strong&gt;, solo afectan la etapa de &lt;strong&gt;composición&lt;/strong&gt;. No requieren recalcular el layout ni repintar, por lo que son las propiedades óptimas para animar de forma fluida a 60 fps.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Prefiere animar &lt;code&gt;transform&lt;/code&gt; y &lt;code&gt;opacity&lt;/code&gt; en lugar de &lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt; o &lt;code&gt;left&lt;/code&gt;. Estas últimas disparan layout y paint en cada frame, lo que produce animaciones entrecortadas.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="transformaciones-en-3d"&gt;Transformaciones en 3D&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;transform&lt;/code&gt; también opera en tres dimensiones. Puedes rotar sobre cualquier eje con &lt;code&gt;rotateX()&lt;/code&gt;, &lt;code&gt;rotateY()&lt;/code&gt; y &lt;code&gt;rotateZ()&lt;/code&gt;. El efecto depende de la &lt;strong&gt;perspectiva&lt;/strong&gt;: la distancia simulada entre el observador y el elemento. A menor perspectiva, más pronunciado el efecto 3D.&lt;/p&gt;
&lt;p&gt;Hay dos formas de aplicarla:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/* 1. Función dentro de transform (afecta solo a ese elemento) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;box&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;perspective&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;200&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;) &lt;span style="color:#e5c07b"&gt;rotateX&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;30&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/* 2. Propiedad en el contenedor (perspectiva compartida) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;row&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;perspective&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;200&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;box&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;transform&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;rotateX&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;30&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:flex;justify-content:center;gap:2rem;perspective:300px;"&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em 1em;border-radius:.4em;transform:rotateX(35deg);"&gt;rotateX(35deg)&lt;/div&gt;
 &lt;div style="background:#16828d;color:#fff;padding:1.5em 1em;border-radius:.4em;transform:rotateY(35deg);"&gt;rotateY(35deg)&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Una rotación de 180° voltea el elemento como un espejo. La propiedad &lt;code&gt;backface-visibility&lt;/code&gt; controla si la cara trasera es visible, lo que habilita efectos como las tarjetas que se voltean. Un recurso clásico para profundizar es &lt;a href="https://3dtransforms.desandro.com/card-flip"




 target="_blank"
 


&gt;Intro to CSS 3D transforms&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Las transiciones suavizan los cambios de estado y las transformaciones manipulan la geometría sin tocar el layout. La regla de oro del rendimiento es animar &lt;code&gt;transform&lt;/code&gt; y &lt;code&gt;opacity&lt;/code&gt;, que solo afectan la etapa de composición. Con curvas de Bézier afinadas y un uso consciente del pipeline, tus animaciones serán fluidas y eficientes.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 La entrega final de la serie aborda la &lt;strong&gt;modularización y los patrones de diseño&lt;/strong&gt; en CSS: cómo organizar tus estilos en componentes mantenibles con metodologías como BEM.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>TypeScript: Introducción y configuración del entorno</title><link>https://blog.dacadev.com/programacion/typescript/introduccion-a-typescript/</link><pubDate>Sun, 14 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/typescript/introduccion-a-typescript/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende qué es TypeScript, cómo funciona su compilador, cómo instalarlo y configurar tsconfig.json para iniciar un proyecto profesional con tipado estático.</description><media:content url="https://blog.dacadev.com/images/programming/typescript/introduction/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#cómo-se-ejecuta-el-código-ast-bytecode-y-runtime"&gt;¿Cómo se ejecuta el código? AST, bytecode y runtime&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-sistema-de-tipos"&gt;El sistema de tipos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#instalación-de-typescript"&gt;Instalación de TypeScript&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tsconfigjson-el-corazón-de-la-configuración"&gt;tsconfig.json: el corazón de la configuración&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-archivo-de-entrada-indexts"&gt;El archivo de entrada: index.ts&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#hola-mundo-y-la-verificación-de-tipos-en-acción"&gt;Hola mundo y la verificación de tipos en acción&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#watch-mode-compilación-continua"&gt;Watch mode: compilación continua&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este artículo abre la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Aquí analizaremos qué problema resuelve el tipado estático, cómo opera el compilador &lt;code&gt;tsc&lt;/code&gt; y cómo dejar listo un proyecto profesional con &lt;code&gt;tsconfig.json&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;JavaScript resuelve los tipos en tiempo de ejecución. Esto significa que un error tan trivial como pasar un &lt;code&gt;string&lt;/code&gt; donde se esperaba un &lt;code&gt;number&lt;/code&gt; solo se manifiesta cuando el código ya está corriendo, frecuentemente en producción y bajo la forma de un &lt;code&gt;NaN&lt;/code&gt; silencioso o una excepción difícil de rastrear. &lt;strong&gt;TypeScript&lt;/strong&gt; ataca este problema en la raíz: agrega un sistema de tipos estático sobre JavaScript que traslada la detección de errores desde el runtime hacia el tiempo de compilación.&lt;/p&gt;
&lt;h2 id="cómo-se-ejecuta-el-código-ast-bytecode-y-runtime"&gt;¿Cómo se ejecuta el código? AST, bytecode y runtime&lt;/h2&gt;
&lt;p&gt;Para entender qué aporta TypeScript conviene recordar el ciclo de vida de un programa en un motor de JavaScript:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;El programa se parsea hacia un &lt;strong&gt;AST&lt;/strong&gt; (Abstract Syntax Tree).&lt;/li&gt;
&lt;li&gt;El AST se compila a &lt;strong&gt;bytecode&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;El bytecode es evaluado por el &lt;strong&gt;runtime&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;TypeScript se inserta antes de este flujo. El compilador &lt;code&gt;tsc&lt;/code&gt; toma tu código &lt;code&gt;.ts&lt;/code&gt;, construye su propio AST, lo somete al &lt;strong&gt;typechecker&lt;/strong&gt; y, si todo es válido, emite JavaScript estándar que cualquier motor puede ejecutar.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[Código TypeScript] --&gt; B[AST de TypeScript]
 B --&gt; C{Typechecker}
 C -- válido --&gt; D[JavaScript emitido]
 C -- error --&gt; E[Error en compilación]
 D --&gt; F[AST de JavaScript]
 F --&gt; G[Bytecode]
 G --&gt; H[Runtime]
&lt;/pre&gt;

&lt;p&gt;La conclusión clave: el typechecker es una capa de verificación que se ejecuta &lt;strong&gt;antes&lt;/strong&gt; de generar el JavaScript final. Los errores de tipo nunca llegan al runtime porque la compilación se detiene antes.&lt;/p&gt;
&lt;h2 id="el-sistema-de-tipos"&gt;El sistema de tipos&lt;/h2&gt;
&lt;p&gt;TypeScript admite tanto anotaciones de tipo explícitas como inferencia automática. Ambas estrategias coexisten en el mismo archivo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// a es number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// b es string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt;[] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;// c es un arreglo de booleanos
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// a es number (inferido)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// b es string (inferido)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;// c es boolean[] (inferido)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Apóyate en la inferencia siempre que el tipo sea evidente y reserva las anotaciones explícitas para las fronteras del sistema: firmas de funciones, APIs públicas y estructuras de datos compartidas. Esto reduce el ruido sin sacrificar seguridad.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;La diferencia esencial frente a JavaScript se resume así:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Característica del sistema de tipos&lt;/th&gt;
 &lt;th&gt;JavaScript&lt;/th&gt;
 &lt;th&gt;TypeScript&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;¿Cómo se enlazan los tipos?&lt;/td&gt;
 &lt;td&gt;Dinámicamente&lt;/td&gt;
 &lt;td&gt;Estáticamente&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;¿Se convierten automáticamente?&lt;/td&gt;
 &lt;td&gt;Sí&lt;/td&gt;
 &lt;td&gt;No (en general)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;¿Cuándo se verifican?&lt;/td&gt;
 &lt;td&gt;En tiempo de ejecución&lt;/td&gt;
 &lt;td&gt;En tiempo de compilación&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;¿Cuándo afloran los errores?&lt;/td&gt;
 &lt;td&gt;En ejecución&lt;/td&gt;
 &lt;td&gt;En compilación&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="instalación-de-typescript"&gt;Instalación de TypeScript&lt;/h2&gt;
&lt;p&gt;TypeScript se distribuye como un paquete de Node, por lo que necesitas tener &lt;strong&gt;Node.js&lt;/strong&gt; instalado. Inicializa el proyecto y agrega las dependencias de desarrollo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm init -y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install --save-dev typescript @types/node
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;@types/node&lt;/code&gt; aporta las definiciones de tipos del entorno de ejecución de Node, indispensables si vas a trabajar en el backend.&lt;/p&gt;
&lt;h2 id="tsconfigjson-el-corazón-de-la-configuración"&gt;tsconfig.json: el corazón de la configuración&lt;/h2&gt;
&lt;p&gt;El archivo &lt;code&gt;tsconfig.json&lt;/code&gt;, ubicado en la raíz del proyecto, define cómo el compilador interpreta y transforma tu código. Una configuración base sólida luce así:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;compilerOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;es2015&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;module&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;commonjs&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;outDir&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;dist&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;sourceMap&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;strict&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;es2015&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;&amp;#34;include&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;src&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cada opción cumple un rol concreto:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;include&lt;/code&gt;: indica las rutas donde &lt;code&gt;tsc&lt;/code&gt; debe buscar los archivos a compilar.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lib&lt;/code&gt;: declara qué librerías de tipos (APIs del entorno) asume disponibles el proyecto.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module&lt;/code&gt;: define el sistema de módulos del código emitido (&lt;code&gt;commonjs&lt;/code&gt;, &lt;code&gt;esnext&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;outDir&lt;/code&gt;: ubicación de los archivos JavaScript compilados.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sourceMap&lt;/code&gt;: genera &lt;em&gt;source maps&lt;/em&gt; para depurar el TypeScript original desde el navegador o Node.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strict&lt;/code&gt;: habilita el conjunto completo de comprobaciones estrictas. Es la opción que más valor aporta.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;target&lt;/code&gt;: versión de JavaScript a la que se transpila el código.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Puedes consultar el catálogo completo de opciones en la &lt;a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html"




 target="_blank"
 


&gt;documentación oficial de tsc&lt;/a&gt;, o explorarlas desde la terminal:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx tsc --help
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La opción &lt;code&gt;strict&lt;/code&gt; no es opcional en un proyecto serio. Activarla desde el primer commit evita una migración dolorosa más adelante, cuando el código ya arrastra cientos de tipos implícitos &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="el-archivo-de-entrada-indexts"&gt;El archivo de entrada: index.ts&lt;/h2&gt;
&lt;p&gt;El punto de entrada convencional es &lt;code&gt;src/index.ts&lt;/code&gt;. Comencemos con el clásico mensaje de prueba:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;hello world from TS!&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Compila el proyecto y ejecútalo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx tsc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node ./dist/index.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;tsc&lt;/code&gt; lee la configuración de &lt;code&gt;tsconfig.json&lt;/code&gt;, transpila todo lo que esté bajo &lt;code&gt;src&lt;/code&gt; y deposita el resultado en &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="hola-mundo-y-la-verificación-de-tipos-en-acción"&gt;Hola mundo y la verificación de tipos en acción&lt;/h2&gt;
&lt;p&gt;Observemos cómo el typechecker protege contra asignaciones inválidas:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Hola mundo&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;David Casas&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// msg = 123 // Error: number no es asignable a string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Al compilar, TypeScript transpila a JavaScript plano eliminando las anotaciones:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;var&lt;/span&gt; &lt;span style="color:#e06c75"&gt;msg&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Hola mundo&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;David Casas&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El tipo &lt;code&gt;string&lt;/code&gt; desaparece del código emitido porque su único propósito era validar en compilación. Esta propiedad —los tipos se borran tras la verificación— se conoce como &lt;em&gt;type erasure&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="watch-mode-compilación-continua"&gt;Watch mode: compilación continua&lt;/h2&gt;
&lt;p&gt;Compilar manualmente tras cada cambio rompe el flujo de trabajo. El compilador incluye un &lt;strong&gt;modo observador&lt;/strong&gt; que recompila de forma incremental cada vez que detecta una modificación:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx tsc --watch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# o su forma corta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npx tsc -w
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mantén este proceso abierto en una terminal mientras desarrollas: cada vez que guardes un archivo &lt;code&gt;.ts&lt;/code&gt;, verás de inmediato los errores de tipo o la salida actualizada en &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;TypeScript no reemplaza a JavaScript; lo eleva añadiendo una capa de verificación estática que captura errores antes de ejecutar una sola línea. Con Node instalado, un &lt;code&gt;tsconfig.json&lt;/code&gt; en modo &lt;code&gt;strict&lt;/code&gt; y el compilador en &lt;em&gt;watch mode&lt;/em&gt;, ya tienes un entorno profesional listo para los siguientes temas de la serie.&lt;/p&gt;
&lt;p&gt;En el próximo artículo profundizaremos en los &lt;strong&gt;tipos básicos&lt;/strong&gt; del lenguaje: &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;unknown&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;symbol&lt;/code&gt;, objetos, uniones e intersecciones.&lt;/p&gt;</content:encoded></item><item><title>Estilos CSS: Fondos, gradientes y sombras</title><link>https://blog.dacadev.com/programacion/estilos-css/backgrounds-y-sombras/</link><pubDate>Fri, 12 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/backgrounds-y-sombras/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a trabajar con fondos en CSS: las propiedades background, gradientes lineales y radiales, modos de mezcla y sombras con box-shadow y text-shadow.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/06-backgrounds-y-sombras-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#la-familia-background"&gt;La familia background&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#gradientes-lineales"&gt;Gradientes lineales&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#gradientes-lineales-repetitivos"&gt;Gradientes lineales repetitivos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#gradientes-radiales"&gt;Gradientes radiales&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#combinar-múltiples-fondos"&gt;Combinar múltiples fondos&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#texturas-con-blend-modes"&gt;Texturas con blend modes&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#sombras-box-shadow-y-text-shadow"&gt;Sombras: box-shadow y text-shadow&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#sombras-interiores-para-feedback"&gt;Sombras interiores para feedback&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Los fondos y las sombras son las herramientas con las que CSS aporta profundidad, textura y jerarquía visual sin necesidad de imágenes externas. Un gradiente bien construido reemplaza un archivo PNG; una sombra sutil comunica que un botón es interactivo. Dominar estas propiedades te permite crear interfaces ricas con código puro, ligero y escalable.&lt;/p&gt;
&lt;p&gt;Esta es la sexta entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Recorreremos la familia de propiedades &lt;code&gt;background&lt;/code&gt;, los gradientes lineales y radiales, los modos de mezcla y las sombras de caja y de texto.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Aprenderás a generar gradientes y patrones sin imágenes, a combinar varias capas de fondo y a usar &lt;code&gt;box-shadow&lt;/code&gt; y &lt;code&gt;text-shadow&lt;/code&gt; para dar realismo y feedback a tus componentes.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="la-familia-background"&gt;La familia background&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;background&lt;/code&gt; es una propiedad abreviada que agrupa ocho propiedades individuales:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background-image&lt;/code&gt; — una imagen o un gradiente generado.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-position&lt;/code&gt; — la posición inicial del fondo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-size&lt;/code&gt; — el tamaño de renderizado (&lt;code&gt;cover&lt;/code&gt;, &lt;code&gt;contain&lt;/code&gt;, valores explícitos).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-repeat&lt;/code&gt; — si la imagen se repite en mosaico.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-origin&lt;/code&gt; — respecto a qué caja se posiciona (border, padding o content).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-clip&lt;/code&gt; — hasta qué caja se extiende el fondo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-attachment&lt;/code&gt; — si el fondo se desplaza con el contenido o queda fijo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-color&lt;/code&gt; — un color sólido que se renderiza detrás de la imagen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gradientes-lineales"&gt;Gradientes lineales&lt;/h2&gt;
&lt;p&gt;Un gradiente es una transición de colores generada por una función de CSS, sin archivos. &lt;code&gt;linear-gradient()&lt;/code&gt; crea una transición a lo largo de una dirección.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;fade&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;linear-gradient&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;to&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;right&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;margin:1rem 0;"&gt;
 &lt;div style="height:80px;border-radius:.4em;background-image:linear-gradient(to right,#fff,#2a9da9);"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;La función acepta una dirección (&lt;code&gt;to right&lt;/code&gt;, &lt;code&gt;90deg&lt;/code&gt;, etc.) y una lista de colores. Puedes incluir más de dos colores y fijar su posición con porcentajes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;fade&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;linear-gradient&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;90&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#c0392b&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt; &lt;span style="color:#d19a66"&gt;50&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt; &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;margin:1rem 0;"&gt;
 &lt;div style="height:80px;border-radius:.4em;background-image:linear-gradient(90deg,#c0392b 0%,#fff 50%,#2a9da9 100%);"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="gradientes-lineales-repetitivos"&gt;Gradientes lineales repetitivos&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;repeating-linear-gradient()&lt;/code&gt; crea patrones que se repiten, útil para texturas como rayas:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;rayas&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;repeating-linear-gradient&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;-45&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;deg&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#16828d&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#16828d&lt;/span&gt; &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;margin:1rem 0;"&gt;
 &lt;div style="height:50px;border-radius:.4em;background-image:repeating-linear-gradient(-45deg,#2a9da9,#2a9da9 10px,#16828d 10px,#16828d 20px);"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="gradientes-radiales"&gt;Gradientes radiales&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;radial-gradient()&lt;/code&gt; genera una transición circular o elíptica que irradia desde un punto, en lugar de seguir una dirección lineal.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;brillo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;radial-gradient&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;margin:1rem 0;"&gt;
 &lt;div style="height:120px;border-radius:.4em;background-image:radial-gradient(circle,#fff,#2a9da9);"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="combinar-múltiples-fondos"&gt;Combinar múltiples fondos&lt;/h2&gt;
&lt;p&gt;Puedes apilar varias capas de fondo separándolas con comas. La primera capa queda al frente. Esto permite, por ejemplo, superponer un gradiente sobre una imagen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;heroe&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;linear-gradient&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;to&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;bottom&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;42&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;157&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;169&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0.6&lt;/span&gt;), &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;22&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;130&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;141&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0.9&lt;/span&gt;)),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;url&lt;/span&gt;(&lt;span style="color:#98c379"&gt;foto.jpg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-size&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;cover&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;margin:1rem 0;"&gt;
 &lt;div style="height:120px;border-radius:.4em;display:flex;align-items:center;justify-content:center;color:#fff;font-family:Helvetica,Arial,sans-serif;font-weight:bold;background-image:linear-gradient(135deg,rgba(42,157,169,.85),rgba(22,130,141,.95)),repeating-linear-gradient(45deg,#888,#888 8px,#777 8px,#777 16px);"&gt;Gradiente sobre una textura de fondo&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="texturas-con-blend-modes"&gt;Texturas con blend modes&lt;/h3&gt;
&lt;p&gt;La propiedad &lt;code&gt;background-blend-mode&lt;/code&gt; mezcla las capas de fondo entre sí (con modos como &lt;code&gt;multiply&lt;/code&gt;, &lt;code&gt;soft-light&lt;/code&gt;, &lt;code&gt;overlay&lt;/code&gt;), añadiendo textura a una imagen sin editarla en un programa externo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;textura&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;url&lt;/span&gt;(&lt;span style="color:#98c379"&gt;rayones.png&lt;/span&gt;), &lt;span style="color:#e5c07b"&gt;url&lt;/span&gt;(&lt;span style="color:#98c379"&gt;foto.jpg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-blend-mode&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;soft-light&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="sombras-box-shadow-y-text-shadow"&gt;Sombras: box-shadow y text-shadow&lt;/h2&gt;
&lt;p&gt;CSS permite añadir sombras tanto a las cajas (&lt;code&gt;box-shadow&lt;/code&gt;) como al texto (&lt;code&gt;text-shadow&lt;/code&gt;). Ambas reciben los mismos parámetros básicos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Desplazamiento horizontal y vertical (&lt;code&gt;offset-x&lt;/code&gt;, &lt;code&gt;offset-y&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;El radio de difuminado (&lt;code&gt;blur&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;(opcional) El radio de expansión (&lt;code&gt;spread&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;El color de la sombra.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;tarjeta&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-shadow&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.2&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0.25&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;titulo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;text-shadow&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt; &lt;span style="color:#d19a66"&gt;4&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0.4&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#f4f6f7;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;display:flex;gap:1.5rem;flex-wrap:wrap;align-items:center;"&gt;
 &lt;div style="background:#fff;color:#111;padding:1.2em 1.5em;border-radius:.5em;box-shadow:0 .2em .5em rgba(0,0,0,.25);"&gt;Tarjeta con &lt;code&gt;box-shadow&lt;/code&gt;&lt;/div&gt;
 &lt;span style="font-size:1.6rem;font-weight:bold;color:#2a9da9;text-shadow:2px 2px 4px rgba(0,0,0,.4);"&gt;Texto con text-shadow&lt;/span&gt;
&lt;/div&gt;
&lt;h3 id="sombras-interiores-para-feedback"&gt;Sombras interiores para feedback&lt;/h3&gt;
&lt;p&gt;La palabra clave &lt;code&gt;inset&lt;/code&gt; convierte la sombra en interior, perfecta para simular que un botón está presionado. Combinada con pseudo-clases como &lt;code&gt;:active&lt;/code&gt;, crea componentes con feedback táctil:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;boton&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-image&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;linear-gradient&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;to&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;bottom&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;#16828d&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;box-shadow&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0.4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;boton&lt;/span&gt;:&lt;span style="color:#61afef"&gt;active&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;box-shadow&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;inset&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#d19a66"&gt;#0d4f56&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;inset&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;,&lt;span style="color:#d19a66"&gt;0.4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1.5rem;background:#fff;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;style&gt;
 .csbtn { padding:1em 1.5em; border:0; font-size:.9rem; color:#fff; border-radius:.5em; cursor:pointer; background-image:linear-gradient(to bottom,#2a9da9,#16828d); box-shadow:.1em .1em .5em rgba(0,0,0,.4); }
 .csbtn:active { box-shadow:inset 0 0 .5em #0d4f56, inset 0 .5em 1em rgba(0,0,0,.4); }
 &lt;/style&gt;
 &lt;button class="csbtn" type="button"&gt;Mantén presionado este botón&lt;/button&gt;
 &lt;p style="margin:.75rem 0 0;color:#555;"&gt;Al pulsarlo, la sombra interior simula el hundido físico.&lt;/p&gt;
&lt;/div&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Las sombras se renderizan en la capa de composición y son baratas de animar. Una transición sutil de &lt;code&gt;box-shadow&lt;/code&gt; en &lt;code&gt;:hover&lt;/code&gt; comunica interactividad con un costo de rendimiento mínimo.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Los gradientes y las sombras te permiten construir interfaces con profundidad y textura usando solo CSS, evitando peticiones de red y archivos de imagen. Apilar capas de fondo, mezclarlas con blend modes y aplicar sombras interiores son técnicas que elevan la calidad visual de cualquier componente.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 La próxima entrega cubre &lt;strong&gt;transiciones y transformaciones&lt;/strong&gt;: cómo animar cambios de estado de forma fluida y manipular la geometría de los elementos con &lt;code&gt;transform&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Estilos CSS: Posicionamiento, z-index y diseño responsive</title><link>https://blog.dacadev.com/programacion/estilos-css/posicionamiento-y-responsive/</link><pubDate>Wed, 10 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/posicionamiento-y-responsive/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina el posicionamiento en CSS: static, relative, absolute, fixed y sticky, los contextos de apilamiento con z-index y el diseño responsive con media queries.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/05-posicionamiento-y-responsive-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#la-propiedad-position"&gt;La propiedad position&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#fixed-anclado-al-viewport"&gt;Fixed: anclado al viewport&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#absolute-relativo-al-ancestro-posicionado"&gt;Absolute: relativo al ancestro posicionado&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#relative-desplazamiento-sin-salir-del-flujo"&gt;Relative: desplazamiento sin salir del flujo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#sticky-lo-mejor-de-relative-y-fixed"&gt;Sticky: lo mejor de relative y fixed&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#stacking-contexts-y-z-index"&gt;Stacking contexts y z-index&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#responsive-estilos-que-se-adaptan"&gt;Responsive: estilos que se adaptan&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#media-queries"&gt;Media queries&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#breakpoints-con-mobile-first"&gt;Breakpoints con mobile first&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#estilos-para-impresión"&gt;Estilos para impresión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Hasta ahora hemos trabajado con elementos que viven en el flujo normal del documento. El posicionamiento rompe ese flujo: te permite anclar una cabecera al viewport, superponer un modal, desplegar un menú o fijar una barra lateral mientras el usuario hace scroll. Combinado con &lt;code&gt;z-index&lt;/code&gt; y las media queries, el posicionamiento es la base de las interacciones dinámicas y del diseño adaptable.&lt;/p&gt;
&lt;p&gt;Esta es la quinta entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Cubriremos los cinco valores de &lt;code&gt;position&lt;/code&gt;, los contextos de apilamiento con &lt;code&gt;z-index&lt;/code&gt; y los fundamentos del diseño &lt;strong&gt;responsive&lt;/strong&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Entenderás cuándo usar cada tipo de posicionamiento, por qué &lt;code&gt;z-index&lt;/code&gt; a veces &amp;ldquo;no funciona&amp;rdquo; por culpa de los contextos de apilamiento, y cómo escribir media queries con un enfoque &lt;em&gt;mobile first&lt;/em&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="la-propiedad-position"&gt;La propiedad position&lt;/h2&gt;
&lt;p&gt;La propiedad &lt;code&gt;position&lt;/code&gt; acepta cinco valores que cambian cómo se ubica un elemento:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;static&lt;/code&gt; (por defecto) — el elemento permanece en el flujo normal.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;relative&lt;/code&gt; — se desplaza respecto a su posición original sin salir del flujo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;absolute&lt;/code&gt; — se extrae del flujo y se posiciona respecto a su ancestro posicionado más cercano.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fixed&lt;/code&gt; — se extrae del flujo y se posiciona respecto al viewport.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sticky&lt;/code&gt; — combina &lt;code&gt;relative&lt;/code&gt; y &lt;code&gt;fixed&lt;/code&gt; según el scroll.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Las propiedades &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt; y &lt;code&gt;left&lt;/code&gt; controlan la ubicación (y, en algunos casos, el tamaño) de los elementos posicionados.&lt;/p&gt;
&lt;h2 id="fixed-anclado-al-viewport"&gt;Fixed: anclado al viewport&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;position: fixed&lt;/code&gt; extrae el elemento del flujo normal —los demás se reorganizan como si no existiera— y lo ancla a una posición relativa al viewport, donde permanece aunque el usuario haga scroll. Es la base de los &lt;strong&gt;modales&lt;/strong&gt;: un fondo semitransparente que cubre toda la pantalla y un cuerpo centrado encima.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;modal-backdrop&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;fixed&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;top&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;right&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;bottom&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;left&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;rgba&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;modal-body&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;fixed&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;top&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;bottom&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;right&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;left&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background-color&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;white&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;overflow&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Al posicionar no estás obligado a declarar los cuatro lados. Si omites &lt;code&gt;bottom&lt;/code&gt; y &lt;code&gt;height&lt;/code&gt;, la altura la determina el contenido de forma natural. Combinar lados con &lt;code&gt;width&lt;/code&gt;/&lt;code&gt;height&lt;/code&gt; te da control total sobre el tamaño.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="absolute-relativo-al-ancestro-posicionado"&gt;Absolute: relativo al ancestro posicionado&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;position: absolute&lt;/code&gt; también extrae el elemento del flujo, pero se posiciona respecto al primer ancestro que tenga una posición distinta de &lt;code&gt;static&lt;/code&gt;. Si ningún ancestro está posicionado, usa el &lt;em&gt;bloque contenedor inicial&lt;/em&gt; (el tamaño del viewport).&lt;/p&gt;
&lt;p&gt;Este es el patrón para colocar un botón de cierre en la esquina de un modal: el padre se marca como &lt;code&gt;position: relative&lt;/code&gt; y el botón como &lt;code&gt;position: absolute&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;modal-body&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;relative&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;modal-close&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;absolute&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;top&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;right&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.3&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="position:relative;background:#eaf2f8;padding:1.5em;border-radius:.4em;min-height:4em;"&gt;
 &lt;span style="position:absolute;top:.4em;right:.4em;background:#c0392b;color:#fff;padding:.2em .5em;border-radius:.3em;font-size:.8em;cursor:pointer;"&gt;✕&lt;/span&gt;
 &lt;strong&gt;Cuerpo del modal&lt;/strong&gt;
 &lt;p style="margin:.4rem 0 0;"&gt;El botón de cierre está posicionado en la esquina con &lt;code&gt;absolute&lt;/code&gt; respecto a este contenedor &lt;code&gt;relative&lt;/code&gt;.&lt;/p&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="relative-desplazamiento-sin-salir-del-flujo"&gt;Relative: desplazamiento sin salir del flujo&lt;/h2&gt;
&lt;p&gt;A diferencia de los anteriores, &lt;code&gt;position: relative&lt;/code&gt; &lt;strong&gt;no&lt;/strong&gt; extrae el elemento del flujo; lo traslada respecto a su posición original, dejando su hueco intacto. Tampoco permite redimensionarlo con la combinación de lados.&lt;/p&gt;
&lt;p&gt;Su uso más frecuente es establecer un &lt;strong&gt;bloque contenedor&lt;/strong&gt; para descendientes absolutos. Es la base de un menú desplegable: el contenedor es &lt;code&gt;relative&lt;/code&gt; y el menú es &lt;code&gt;absolute&lt;/code&gt;, mostrándose con &lt;code&gt;:hover&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;dropdown&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;relative&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;inline-block&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;dropdown-menu&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;absolute&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;top&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;%&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;left&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;none&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;dropdown&lt;/span&gt;:&lt;span style="color:#61afef"&gt;hover&lt;/span&gt; .&lt;span style="color:#e5c07b"&gt;dropdown-menu&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;block&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;min-height:9em;"&gt;
 &lt;style&gt;
 .csdrop { position:relative; display:inline-block; }
 .csdrop-label { padding:.5em 1.5em; border:1px solid #ccc; background:#eee; cursor:pointer; border-radius:.3em; }
 .csdrop-menu { position:absolute; top:100%; left:0; min-width:160px; background:#fff; border:1px solid #999; border-radius:.3em; display:none; margin:0; padding:0; list-style:none; box-shadow:0 4px 12px rgba(0,0,0,.15); z-index:1; }
 .csdrop:hover .csdrop-menu { display:block; }
 .csdrop-menu li a { display:block; padding:.5em 1.5em; color:#2a7ae2; text-decoration:none; }
 .csdrop-menu li a:hover { background:#f0f0f0; }
 &lt;/style&gt;
 &lt;div class="csdrop"&gt;
 &lt;div class="csdrop-label"&gt;Menú principal ▾&lt;/div&gt;
 &lt;ul class="csdrop-menu"&gt;
 &lt;li&gt;&lt;a href="#posicionamiento-y-responsive"&gt;Inicio&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#posicionamiento-y-responsive"&gt;Productos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#posicionamiento-y-responsive"&gt;Contacto&lt;/a&gt;&lt;/li&gt;
 &lt;/ul&gt;
 &lt;/div&gt;
 &lt;p style="margin:.75rem 0 0;color:#555;"&gt;Pasa el cursor sobre el botón para desplegar el menú.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="sticky-lo-mejor-de-relative-y-fixed"&gt;Sticky: lo mejor de relative y fixed&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;position: sticky&lt;/code&gt; mantiene el elemento en su posición normal hasta que, al hacer scroll, alcanza el umbral definido por &lt;code&gt;top&lt;/code&gt;/&lt;code&gt;bottom&lt;/code&gt;; en ese momento se &amp;ldquo;pega&amp;rdquo; como si fuera &lt;code&gt;fixed&lt;/code&gt;. Cuando el contenido vuelve, recupera su comportamiento relativo. Es ideal para barras laterales y cabeceras de sección que deben permanecer visibles.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;afijo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;sticky&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;top&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="stacking-contexts-y-z-index"&gt;Stacking contexts y z-index&lt;/h2&gt;
&lt;p&gt;Cuando varios elementos posicionados se solapan, &lt;code&gt;z-index&lt;/code&gt; controla el orden de apilamiento en el eje Z. Acepta enteros positivos y negativos: a mayor valor, más al frente.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;uno&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;relative&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;z-index&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;dos&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;relative&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;z-index&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* queda por encima de .uno */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aquí está la trampa que confunde a muchos: &lt;strong&gt;cada elemento posicionado con &lt;code&gt;z-index&lt;/code&gt; crea su propio contexto de apilamiento&lt;/strong&gt;. Un hijo dentro de un contexto con &lt;code&gt;z-index: 1&lt;/code&gt; nunca podrá superar a un elemento de un contexto hermano con &lt;code&gt;z-index: 2&lt;/code&gt;, aunque el hijo tenga &lt;code&gt;z-index: 99999&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;z-index&lt;/code&gt; tiene dos &amp;ldquo;gotchas&amp;rdquo;: solo funciona sobre elementos posicionados (cualquier &lt;code&gt;position&lt;/code&gt; distinto de &lt;code&gt;static&lt;/code&gt;), y al usarlo creas un nuevo contexto de apilamiento. Si un &lt;code&gt;z-index&lt;/code&gt; enorme &amp;ldquo;no funciona&amp;rdquo;, casi siempre es porque su elemento está atrapado en un contexto de apilamiento de menor prioridad.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="responsive-estilos-que-se-adaptan"&gt;Responsive: estilos que se adaptan&lt;/h2&gt;
&lt;p&gt;La enorme variedad de pantallas obliga a diseñar interfaces que respondan a distintos tamaños. La filosofía &lt;strong&gt;mobile first&lt;/strong&gt; consiste en escribir primero los estilos para móvil y luego ampliarlos progresivamente hacia tablets y escritorio.&lt;/p&gt;
&lt;h3 id="media-queries"&gt;Media queries&lt;/h3&gt;
&lt;p&gt;Una &lt;strong&gt;media query&lt;/strong&gt; aplica un bloque de CSS solo cuando se cumple una condición sobre el viewport. Conviene usar &lt;code&gt;em&lt;/code&gt; en los umbrales para que respeten el zoom y la configuración del usuario.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;35em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#e5c07b"&gt;titulo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2.25&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Puedes combinar condiciones con lógica:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/* AND: ambas condiciones */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;20em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; &lt;span style="color:#e06c75"&gt;and&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;max-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;35em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { &lt;span style="color:#7f848e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;/* OR: cualquiera de las dos */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;max-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;20em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;),&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;35em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { &lt;span style="color:#7f848e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Entre las características consultables están &lt;code&gt;min-width&lt;/code&gt;, &lt;code&gt;max-width&lt;/code&gt;, &lt;code&gt;min-height&lt;/code&gt;, &lt;code&gt;orientation: landscape | portrait&lt;/code&gt; y &lt;code&gt;min-resolution: 2dppx&lt;/code&gt; (para pantallas retina). El catálogo completo está en la &lt;a href="https://developer.mozilla.org/es/docs/Web/CSS/@media"




 target="_blank"
 


&gt;documentación de &lt;code&gt;@media&lt;/code&gt; en MDN&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="breakpoints-con-mobile-first"&gt;Breakpoints con mobile first&lt;/h3&gt;
&lt;p&gt;Los &lt;strong&gt;breakpoints&lt;/strong&gt; son los puntos donde el diseño cambia de un tamaño a otro. Con el enfoque mobile first, los estilos base sirven al móvil y cada media query añade ajustes para pantallas mayores:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;titulo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* móvil (base) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;35em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { &lt;span style="color:#7f848e"&gt;/* tablet */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#e5c07b"&gt;titulo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;50em&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { &lt;span style="color:#7f848e"&gt;/* escritorio */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#e5c07b"&gt;titulo&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;rem&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;style&gt;
 .csresp { font-size:1.5rem;font-weight:bold;color:#16828d;margin:0; }
 @media (min-width:35em) { .csresp { font-size:2rem; } }
 @media (min-width:50em) { .csresp { font-size:2.5rem; } }
 &lt;/style&gt;
 &lt;p class="csresp"&gt;Este título cambia de tamaño según el ancho&lt;/p&gt;
 &lt;small style="color:#555;"&gt;Redimensiona la ventana para cruzar los breakpoints de 35em y 50em.&lt;/small&gt;
&lt;/div&gt;
&lt;h3 id="estilos-para-impresión"&gt;Estilos para impresión&lt;/h3&gt;
&lt;p&gt;Las media queries también cubren el medio de impresión. &lt;code&gt;@media print&lt;/code&gt; aplica reglas cuando el usuario imprime o exporta a PDF:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#e06c75"&gt;print&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;black&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;background&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;none&lt;/span&gt; &lt;span style="color:#7f848e"&gt;!important&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El posicionamiento te da control fino sobre dónde vive cada elemento: &lt;code&gt;fixed&lt;/code&gt; para modales, &lt;code&gt;absolute&lt;/code&gt; para tooltips y menús, &lt;code&gt;relative&lt;/code&gt; como ancla, y &lt;code&gt;sticky&lt;/code&gt; para elementos que acompañan el scroll. Sumado a un manejo consciente de los contextos de apilamiento y a media queries con enfoque mobile first, tienes las piezas para construir interfaces dinámicas y adaptables.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 La próxima entrega explora los &lt;strong&gt;fondos y las sombras&lt;/strong&gt;: gradientes, modos de mezcla y las propiedades &lt;code&gt;box-shadow&lt;/code&gt; y &lt;code&gt;text-shadow&lt;/code&gt; para dar profundidad a tus componentes.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Estilos CSS: Layouts con Float, Flexbox y Grid</title><link>https://blog.dacadev.com/programacion/estilos-css/layouts-flexbox-grid/</link><pubDate>Mon, 08 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/layouts-flexbox-grid/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a maquetar con CSS: el legado de float y clearfix, el modelo flexible de Flexbox y el sistema bidimensional de CSS Grid, con demostraciones renderizadas.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/04-layouts-flexbox-grid-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#float-el-origen-y-el-clearfix"&gt;Float: el origen y el clearfix&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#flexbox-layout-en-una-dimensión"&gt;Flexbox: layout en una dimensión&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#alinear-ítems-con-justify-content-y-align-items"&gt;Alinear ítems con justify-content y align-items&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#controlar-el-tamaño-flex-grow-flex-shrink-y-flex-basis"&gt;Controlar el tamaño: flex-grow, flex-shrink y flex-basis&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#dirección-y-envoltura"&gt;Dirección y envoltura&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#propiedades-del-ítem"&gt;Propiedades del ítem&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#css-grid-layout-en-dos-dimensiones"&gt;CSS Grid: layout en dos dimensiones&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#una-rejilla-básica"&gt;Una rejilla básica&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#posicionar-ítems-por-líneas"&gt;Posicionar ítems por líneas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#áreas-con-nombre"&gt;Áreas con nombre&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#rejilla-implícita-y-galerías-responsivas"&gt;Rejilla implícita y galerías responsivas&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#flexbox-y-grid-complementarios-no-rivales"&gt;Flexbox y Grid: complementarios, no rivales&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Maquetar es componer la estructura visual de una página: columnas, rejillas, barras laterales, galerías. Durante años se hizo con herramientas que no se diseñaron para ello —&lt;code&gt;float&lt;/code&gt; nació para envolver texto alrededor de imágenes— hasta que llegaron &lt;strong&gt;Flexbox&lt;/strong&gt; y &lt;strong&gt;CSS Grid&lt;/strong&gt;, dos sistemas pensados específicamente para layout. Conocer los tres te permite entender el código heredado y elegir la herramienta correcta para cada problema.&lt;/p&gt;
&lt;p&gt;Esta es la cuarta entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Recorreremos &lt;code&gt;float&lt;/code&gt; y la técnica &lt;code&gt;clearfix&lt;/code&gt;, el modelo unidimensional de Flexbox y el sistema bidimensional de Grid, con ejemplos que puedes ver renderizados.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Aprenderás cuándo sigue siendo útil &lt;code&gt;float&lt;/code&gt;, cómo controlar el tamaño de los ítems con &lt;code&gt;flex&lt;/code&gt;, y cómo posicionar elementos en una rejilla con &lt;code&gt;grid-template&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="float-el-origen-y-el-clearfix"&gt;Float: el origen y el clearfix&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;float&lt;/code&gt; extrae un elemento del flujo normal y lo desplaza hacia un lado de su contenedor; el contenido adyacente fluye a su alrededor. Ese fue su propósito original: envolver texto alrededor de una imagen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;imagen&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;float&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;left&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;margin-right&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="float:left;width:90px;height:90px;background:#2a9da9;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:.4em;margin:0 1em .5em 0;"&gt;float&lt;/div&gt;
 &lt;p style="margin:0;"&gt;Este párrafo fluye alrededor del bloque flotado. El texto se ajusta al margen del elemento extraído del flujo, exactamente el caso de uso para el que &lt;code&gt;float&lt;/code&gt; fue concebido: envolver contenido alrededor de una figura.&lt;/p&gt;
 &lt;div style="clear:both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Cuando usas &lt;code&gt;float&lt;/code&gt;, necesitas &lt;strong&gt;limpiar&lt;/strong&gt; el flujo para que el contenedor vuelva a comportarse con normalidad. El patrón estándar es el &lt;strong&gt;clearfix&lt;/strong&gt;, implementado con un pseudo-elemento:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;clearfix&lt;/span&gt;::&lt;span style="color:#61afef"&gt;before&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;clearfix&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;table&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;content&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;clearfix&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;clear&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;both&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Para layouts modernos, &lt;code&gt;float&lt;/code&gt; casi siempre se reemplaza por Flexbox o Grid. Resérvalo para su propósito original: envolver texto alrededor de un elemento.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="flexbox-layout-en-una-dimensión"&gt;Flexbox: layout en una dimensión&lt;/h2&gt;
&lt;p&gt;Al aplicar &lt;code&gt;display: flex&lt;/code&gt; a un contenedor, este se convierte en un &lt;strong&gt;flex container&lt;/strong&gt; y sus hijos en &lt;strong&gt;flex items&lt;/strong&gt;. Flexbox organiza los ítems a lo largo de un eje principal y los alinea en el eje transversal, ajustando tamaños de forma flexible.&lt;/p&gt;
&lt;p&gt;Un contenedor flex tiene dos ejes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eje principal (main)&lt;/strong&gt; — la dirección en la que se colocan los ítems (horizontal por defecto).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eje transversal (cross)&lt;/strong&gt; — perpendicular al principal.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="alinear-ítems-con-justify-content-y-align-items"&gt;Alinear ítems con justify-content y align-items&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;justify-content&lt;/code&gt; controla la distribución a lo largo del &lt;strong&gt;eje principal&lt;/strong&gt;: &lt;code&gt;flex-start&lt;/code&gt;, &lt;code&gt;flex-end&lt;/code&gt;, &lt;code&gt;center&lt;/code&gt;, &lt;code&gt;space-between&lt;/code&gt;, &lt;code&gt;space-around&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;align-items&lt;/code&gt; controla la alineación en el &lt;strong&gt;eje transversal&lt;/strong&gt;: &lt;code&gt;stretch&lt;/code&gt; (por defecto), &lt;code&gt;flex-start&lt;/code&gt;, &lt;code&gt;flex-end&lt;/code&gt;, &lt;code&gt;center&lt;/code&gt;, &lt;code&gt;baseline&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;barra&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;flex&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;justify-content&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;space-between&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;align-items&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;center&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:flex;justify-content:space-between;align-items:center;background:#eaf2f8;padding:.75rem;border-radius:.4em;"&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:.5em 1em;border-radius:.3em;"&gt;Logo&lt;/span&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:.5em 1em;border-radius:.3em;"&gt;Menú&lt;/span&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:.5em 1em;border-radius:.3em;"&gt;Perfil&lt;/span&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="controlar-el-tamaño-flex-grow-flex-shrink-y-flex-basis"&gt;Controlar el tamaño: flex-grow, flex-shrink y flex-basis&lt;/h3&gt;
&lt;p&gt;La propiedad abreviada &lt;code&gt;flex&lt;/code&gt; agrupa tres propiedades que gobiernan el tamaño de cada ítem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;flex-basis&lt;/code&gt;&lt;/strong&gt; — el tamaño base (de partida) del ítem antes de crecer o encoger. Su valor inicial es &lt;code&gt;auto&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;flex-grow&lt;/code&gt;&lt;/strong&gt; — el factor de crecimiento para repartir el espacio sobrante. &lt;code&gt;0&lt;/code&gt; no crece.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;flex-shrink&lt;/code&gt;&lt;/strong&gt; — el factor de encogimiento cuando falta espacio.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;col-a&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;flex&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* crece para ocupar el espacio sobrante */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;col-b&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;flex&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* crece al doble que col-a */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:flex;gap:.5rem;"&gt;
 &lt;div style="flex:1;background:#2a9da9;color:#fff;padding:1em;border-radius:.4em;text-align:center;"&gt;flex: 1&lt;/div&gt;
 &lt;div style="flex:2;background:#16828d;color:#fff;padding:1em;border-radius:.4em;text-align:center;"&gt;flex: 2 (el doble de ancho)&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="dirección-y-envoltura"&gt;Dirección y envoltura&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;flex-direction&lt;/code&gt; cambia el eje principal: &lt;code&gt;row&lt;/code&gt; (por defecto), &lt;code&gt;row-reverse&lt;/code&gt;, &lt;code&gt;column&lt;/code&gt;, &lt;code&gt;column-reverse&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flex-wrap&lt;/code&gt; permite que los ítems salten a una nueva línea cuando no caben: &lt;code&gt;nowrap&lt;/code&gt; (por defecto), &lt;code&gt;wrap&lt;/code&gt;, &lt;code&gt;wrap-reverse&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flex-flow&lt;/code&gt; es la abreviatura de ambas: &lt;code&gt;flex-flow: row wrap&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="propiedades-del-ítem"&gt;Propiedades del ítem&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;align-self&lt;/code&gt; — sobrescribe &lt;code&gt;align-items&lt;/code&gt; para un ítem concreto.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;order&lt;/code&gt; — reordena los ítems sin tocar el HTML; el valor inicial es &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Flexbox crea automáticamente columnas de igual altura y es la herramienta ideal para centrar un elemento. Para un catálogo de bugs conocidos y sus soluciones, consulta &lt;a href="https://github.com/philipwalton/flexbugs"




 target="_blank"
 


&gt;flexbugs&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="css-grid-layout-en-dos-dimensiones"&gt;CSS Grid: layout en dos dimensiones&lt;/h2&gt;
&lt;p&gt;Mientras Flexbox trabaja en un solo eje, &lt;strong&gt;CSS Grid&lt;/strong&gt; organiza el contenido en &lt;strong&gt;filas y columnas&lt;/strong&gt; simultáneamente. Antes de usarlo conviene fijar su vocabulario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Grid line&lt;/strong&gt; — las líneas que forman la estructura de la rejilla.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grid track&lt;/strong&gt; — el espacio entre dos líneas adyacentes (una fila o una columna).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grid cell&lt;/strong&gt; — la intersección de una fila y una columna.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grid area&lt;/strong&gt; — un rectángulo formado por una o más celdas.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="una-rejilla-básica"&gt;Una rejilla básica&lt;/h3&gt;
&lt;p&gt;Se activa con &lt;code&gt;display: grid&lt;/code&gt; y se definen las pistas con &lt;code&gt;grid-template-columns&lt;/code&gt; y &lt;code&gt;grid-template-rows&lt;/code&gt;. La unidad &lt;code&gt;fr&lt;/code&gt; representa una fracción del espacio disponible.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;grid&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#c678dd"&gt;grid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;grid-template-columns&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fr&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fr&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;gap&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:.5em;"&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;a&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;b&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;c&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;d&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;e&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;f&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;La función &lt;code&gt;repeat()&lt;/code&gt; evita la repetición: &lt;code&gt;grid-template-columns: repeat(3, 1fr)&lt;/code&gt; equivale a &lt;code&gt;1fr 1fr 1fr&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="posicionar-ítems-por-líneas"&gt;Posicionar ítems por líneas&lt;/h3&gt;
&lt;p&gt;Cada línea de la rejilla tiene un número. Con &lt;code&gt;grid-column&lt;/code&gt; y &lt;code&gt;grid-row&lt;/code&gt; indicas dónde empieza y termina un ítem usando la sintaxis &lt;code&gt;inicio / fin&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;destacado&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;grid-column&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;/&lt;/span&gt; &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;; &lt;span style="color:#7f848e"&gt;/* abarca de la línea 1 a la 3 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;grid-row&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;span&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;; &lt;span style="color:#7f848e"&gt;/* abarca dos pistas verticales */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:60px;gap:.5em;"&gt;
 &lt;div style="grid-column:1 / 3;background:#f39c12;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:.4em;"&gt;grid-column: 1 / 3&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:.4em;"&gt;b&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:.4em;"&gt;c&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:.4em;"&gt;d&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:.4em;"&gt;e&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="áreas-con-nombre"&gt;Áreas con nombre&lt;/h3&gt;
&lt;p&gt;La forma más legible de componer un layout es nombrar las áreas con &lt;code&gt;grid-template-areas&lt;/code&gt; y asignar cada elemento con &lt;code&gt;grid-area&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;contenedor&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#c678dd"&gt;grid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;grid-template-areas&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;titulo titulo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;nav nav&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;main aside&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;grid-template-columns&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fr&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;gap&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;header&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;grid-area&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;titulo&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;nav&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;grid-area&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;nav&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;main&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;grid-area&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;main&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;aside&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;grid-area&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;aside&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:grid;grid-template-areas:'titulo titulo' 'nav nav' 'main aside';grid-template-columns:2fr 1fr;gap:.5em;"&gt;
 &lt;div style="grid-area:titulo;background:#16828d;color:#fff;padding:.8em;border-radius:.4em;text-align:center;"&gt;titulo&lt;/div&gt;
 &lt;div style="grid-area:nav;background:#1f6f78;color:#fff;padding:.8em;border-radius:.4em;text-align:center;"&gt;nav&lt;/div&gt;
 &lt;div style="grid-area:main;background:#2a9da9;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;main&lt;/div&gt;
 &lt;div style="grid-area:aside;background:#f39c12;color:#fff;padding:1.5em;border-radius:.4em;text-align:center;"&gt;aside&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="rejilla-implícita-y-galerías-responsivas"&gt;Rejilla implícita y galerías responsivas&lt;/h3&gt;
&lt;p&gt;Cuando no conoces de antemano la cantidad de ítems —por ejemplo, datos que vienen de una API— la &lt;strong&gt;rejilla implícita&lt;/strong&gt; crece automáticamente para acomodarlos. La combinación de &lt;code&gt;auto-fill&lt;/code&gt; con &lt;code&gt;minmax()&lt;/code&gt; produce galerías que se adaptan al ancho disponible sin media queries:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;galeria&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#c678dd"&gt;grid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;grid-template-columns&lt;/span&gt;: &lt;span style="color:#61afef;font-weight:bold"&gt;repeat&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;auto&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;fill&lt;/span&gt;, &lt;span style="color:#61afef;font-weight:bold"&gt;minmax&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;180&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fr&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;gap&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:.5em;"&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.2em;border-radius:.4em;text-align:center;"&gt;1&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.2em;border-radius:.4em;text-align:center;"&gt;2&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.2em;border-radius:.4em;text-align:center;"&gt;3&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.2em;border-radius:.4em;text-align:center;"&gt;4&lt;/div&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1.2em;border-radius:.4em;text-align:center;"&gt;5&lt;/div&gt;
 &lt;/div&gt;
 &lt;small style="display:block;margin-top:.5rem;color:#555;"&gt;Redimensiona la ventana: las columnas se reorganizan solas.&lt;/small&gt;
&lt;/div&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Con Grid solo puedes formar rectángulos. No se pueden crear formas en L o U directamente; se simulan dejando celdas vacías (con &lt;code&gt;.&lt;/code&gt; en &lt;code&gt;grid-template-areas&lt;/code&gt;) o combinando áreas.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="flexbox-y-grid-complementarios-no-rivales"&gt;Flexbox y Grid: complementarios, no rivales&lt;/h2&gt;
&lt;p&gt;No tienes que elegir uno. La combinación más potente es usar &lt;strong&gt;Grid&lt;/strong&gt; para la estructura macro de la página (cabecera, contenido, barra lateral, pie) y &lt;strong&gt;Flexbox&lt;/strong&gt; para alinear el contenido dentro de cada zona (una barra de navegación, una tarjeta, un grupo de botones).&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;float&lt;/code&gt; resuelve el envolvimiento de texto; Flexbox domina el layout en una dimensión y el centrado; Grid organiza estructuras bidimensionales complejas. Elegir la herramienta adecuada para cada problema —y combinarlas— es lo que distingue una maquetación robusta de una llena de parches.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 En la próxima entrega abordamos el &lt;strong&gt;posicionamiento&lt;/strong&gt; (&lt;code&gt;relative&lt;/code&gt;, &lt;code&gt;absolute&lt;/code&gt;, &lt;code&gt;fixed&lt;/code&gt;, &lt;code&gt;sticky&lt;/code&gt;), los contextos de apilamiento con &lt;code&gt;z-index&lt;/code&gt; y el diseño &lt;strong&gt;responsive&lt;/strong&gt; con media queries.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Estilos CSS: Dominando el modelo de caja</title><link>https://blog.dacadev.com/programacion/estilos-css/modelo-de-caja/</link><pubDate>Sat, 06 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/modelo-de-caja/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina el modelo de caja en CSS: content-box vs border-box, control de overflow, alturas orgánicas, centrado vertical, márgenes negativos y colapso de márgenes.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/03-modelo-de-caja-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#las-cuatro-regiones-de-una-caja"&gt;Las cuatro regiones de una caja&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#box-sizing-content-box-vs-border-box"&gt;&lt;code&gt;box-sizing&lt;/code&gt;: content-box vs border-box&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#alturas-el-flujo-normal-manda"&gt;Alturas: el flujo normal manda&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#overflow-qué-hacer-cuando-el-contenido-se-desborda"&gt;&lt;code&gt;overflow&lt;/code&gt;: qué hacer cuando el contenido se desborda&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#centrado-vertical"&gt;Centrado vertical&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#márgenes-negativos"&gt;Márgenes negativos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#colapso-de-márgenes-margin-collapsing"&gt;Colapso de márgenes (margin collapsing)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;El modelo de caja es el sistema con el que CSS calcula el tamaño y el espaciado de cada elemento. Parece trivial, pero es la fuente número uno de layouts impredecibles: un &lt;code&gt;width: 50%&lt;/code&gt; que termina midiendo más de la mitad, dos columnas que no encajan, márgenes que desaparecen sin razón aparente. Todos esos síntomas se explican entendiendo cómo el navegador compone una caja.&lt;/p&gt;
&lt;p&gt;Esta es la tercera entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Analizaremos las cuatro regiones de una caja, el cambio de comportamiento que introduce &lt;code&gt;box-sizing&lt;/code&gt;, el control de &lt;code&gt;overflow&lt;/code&gt;, el manejo de alturas, el centrado vertical y el colapso de márgenes.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Comprenderás por qué &lt;code&gt;box-sizing: border-box&lt;/code&gt; debería ser tu valor por defecto y aprenderás a resolver los problemas clásicos de altura, centrado vertical y colapso de márgenes.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="las-cuatro-regiones-de-una-caja"&gt;Las cuatro regiones de una caja&lt;/h2&gt;
&lt;p&gt;Todo elemento HTML se compone, de adentro hacia afuera, de cuatro capas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;content&lt;/strong&gt; — el área donde vive el contenido (texto, imágenes).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;padding&lt;/strong&gt; — el espacio interno entre el contenido y el borde.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;border&lt;/strong&gt; — el borde que rodea el padding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;margin&lt;/strong&gt; — el espacio externo que separa la caja de sus vecinos.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;div&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;caja&amp;#34;&lt;/span&gt;&amp;gt;content + padding + border + margin&amp;lt;/&lt;span style="color:#e06c75"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px dashed #f39c12;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;div style="background:#fdebd0;padding:1.25rem;border:3px solid #2a9da9;font-family:Helvetica,Arial,sans-serif;color:#111;"&gt;
 &lt;div style="background:#aed6f1;padding:.75rem;"&gt;content&lt;/div&gt;
 &lt;small style="display:block;margin-top:.4rem;color:#555;"&gt;El área azul es el &lt;code&gt;content&lt;/code&gt;; el beige es el &lt;code&gt;padding&lt;/code&gt;; el trazo turquesa es el &lt;code&gt;border&lt;/code&gt;; el espacio punteado exterior es el &lt;code&gt;margin&lt;/code&gt;.&lt;/small&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="box-sizing-content-box-vs-border-box"&gt;&lt;code&gt;box-sizing&lt;/code&gt;: content-box vs border-box&lt;/h2&gt;
&lt;p&gt;La propiedad &lt;code&gt;box-sizing&lt;/code&gt; decide qué incluye el &lt;code&gt;width&lt;/code&gt; y el &lt;code&gt;height&lt;/code&gt; que declaras.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;content-box&lt;/code&gt;&lt;/strong&gt; (valor por defecto) — &lt;code&gt;width&lt;/code&gt; y &lt;code&gt;height&lt;/code&gt; miden &lt;strong&gt;solo&lt;/strong&gt; el contenido. El &lt;code&gt;padding&lt;/code&gt; y el &lt;code&gt;border&lt;/code&gt; se suman &lt;em&gt;por fuera&lt;/em&gt;, agrandando el tamaño final.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;border-box&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;width&lt;/code&gt; y &lt;code&gt;height&lt;/code&gt; miden el conjunto de contenido + padding + border. El tamaño que declaras es el tamaño real renderizado.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mira dos cajas con &lt;code&gt;width: 200px&lt;/code&gt; y &lt;code&gt;padding: 20px&lt;/code&gt;, una con cada modelo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;content-box&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-sizing&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;content-box&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* ancho real: 200 + 40 = 240px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;border-box&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-sizing&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;border-box&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* ancho real: 200px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="box-sizing:content-box;width:200px;padding:20px;border:3px solid #c0392b;background:#fdecea;margin-bottom:.75rem;color:#111;"&gt;content-box → mide 246px en total&lt;/div&gt;
 &lt;div style="box-sizing:border-box;width:200px;padding:20px;border:3px solid #27ae60;background:#eafaf1;color:#111;"&gt;border-box → mide 200px en total&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Por eso es práctica recomendada activar &lt;code&gt;border-box&lt;/code&gt; de forma global, heredándolo para no romper estilos de terceros:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-sizing&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;border-box&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;*,&lt;/span&gt; ::&lt;span style="color:#61afef"&gt;before&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;,&lt;/span&gt; ::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;box-sizing&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;inherit&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Evita los &lt;strong&gt;números mágicos&lt;/strong&gt;: valores arbitrarios (&lt;code&gt;margin-top: 37px&lt;/code&gt;) que &amp;ldquo;cuadran&amp;rdquo; un diseño por casualidad. Haz que el contenido se adapte al contenedor, no al revés.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="alturas-el-flujo-normal-manda"&gt;Alturas: el flujo normal manda&lt;/h2&gt;
&lt;p&gt;La altura de un contenedor es &lt;strong&gt;orgánica&lt;/strong&gt; por defecto: la define su contenido, no el contenedor. Esto tiene dos consecuencias prácticas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Definir &lt;code&gt;height&lt;/code&gt; en porcentaje rara vez funciona, porque se refiere a la altura del padre, que a su vez depende de su contenido.&lt;/li&gt;
&lt;li&gt;Para que un &lt;code&gt;height: 100%&lt;/code&gt; funcione, el padre necesita una altura explícita en unidades absolutas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En lugar de fijar alturas, prefiere restringir el rango con &lt;code&gt;min-height&lt;/code&gt; y &lt;code&gt;max-height&lt;/code&gt;, dejando que el contenido fluya:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;panel&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;min-height&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;6&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;max-height&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;12&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="overflow-qué-hacer-cuando-el-contenido-se-desborda"&gt;&lt;code&gt;overflow&lt;/code&gt;: qué hacer cuando el contenido se desborda&lt;/h2&gt;
&lt;p&gt;Cuando el contenido excede el tamaño de su caja, &lt;code&gt;overflow&lt;/code&gt; define el comportamiento:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Valor&lt;/th&gt;
 &lt;th&gt;Comportamiento&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;visible&lt;/code&gt; (por defecto)&lt;/td&gt;
 &lt;td&gt;El contenido se desborda y permanece visible.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;hidden&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;El contenido que se sale se recorta.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;scroll&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Siempre añade barras de desplazamiento.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;auto&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Añade barras solo si hace falta.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;recorte&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;overflow&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;auto&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;max-height&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="overflow:auto;max-height:5em;border:1px solid #ccc;padding:.5rem;color:#111;"&gt;
 &lt;p style="margin:0 0 .5rem;"&gt;Este contenedor tiene &lt;code&gt;overflow: auto&lt;/code&gt; y una altura máxima.&lt;/p&gt;
 &lt;p style="margin:0 0 .5rem;"&gt;Cuando el contenido supera esa altura, aparece una barra de desplazamiento.&lt;/p&gt;
 &lt;p style="margin:0 0 .5rem;"&gt;Línea adicional para forzar el desbordamiento.&lt;/p&gt;
 &lt;p style="margin:0;"&gt;Y una más para asegurar el scroll.&lt;/p&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Puedes controlar cada eje por separado con &lt;code&gt;overflow-x&lt;/code&gt; y &lt;code&gt;overflow-y&lt;/code&gt;, aunque mezclar valores distintos suele dar resultados poco predecibles.&lt;/p&gt;
&lt;h2 id="centrado-vertical"&gt;Centrado vertical&lt;/h2&gt;
&lt;p&gt;Centrar verticalmente fue durante años un dolor de cabeza en CSS. La propiedad &lt;code&gt;vertical-align&lt;/code&gt; no sirve para esto: solo aplica a elementos &lt;code&gt;inline&lt;/code&gt; y a celdas de tabla. Hoy tenemos varias soluciones según el escenario:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;¿Puedes usar la altura natural?&lt;/strong&gt; Aplica un &lt;code&gt;padding&lt;/code&gt; igual arriba y abajo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;¿Necesitas altura fija?&lt;/strong&gt; Usa &lt;code&gt;display: table-cell&lt;/code&gt; con &lt;code&gt;vertical-align: middle&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El caso general:&lt;/strong&gt; usa &lt;strong&gt;flexbox&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;¿Una sola línea de texto?&lt;/strong&gt; Usa &lt;code&gt;line-height&lt;/code&gt; igual a la altura del contenedor.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;La solución moderna por excelencia es flexbox, que centra en ambos ejes con tres declaraciones:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;centro&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;display&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;flex&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;align-items&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;center&lt;/span&gt;; &lt;span style="color:#7f848e"&gt;/* eje vertical */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;justify-content&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;center&lt;/span&gt;; &lt;span style="color:#7f848e"&gt;/* eje horizontal */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;min-height&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;8&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;div style="display:flex;align-items:center;justify-content:center;min-height:8em;background:#eaf2f8;border-radius:.4em;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;span style="background:#2a9da9;color:#fff;padding:.6em 1.2em;border-radius:.4em;"&gt;Centrado en ambos ejes&lt;/span&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="márgenes-negativos"&gt;Márgenes negativos&lt;/h2&gt;
&lt;p&gt;A diferencia de &lt;code&gt;padding&lt;/code&gt; y &lt;code&gt;border&lt;/code&gt;, los márgenes admiten valores &lt;strong&gt;negativos&lt;/strong&gt;, lo que te permite tirar de un elemento hacia afuera de su posición natural o solaparlo con su vecino.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;solapado&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;margin-top&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;-1.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;div style="background:#2a9da9;color:#fff;padding:1em;border-radius:.4em;"&gt;Bloque base&lt;/div&gt;
 &lt;div style="background:#f39c12;color:#fff;padding:1em;border-radius:.4em;margin-top:-1.5em;margin-left:2em;"&gt;Bloque con &lt;code&gt;margin-top&lt;/code&gt; negativo que se solapa&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="colapso-de-márgenes-margin-collapsing"&gt;Colapso de márgenes (margin collapsing)&lt;/h2&gt;
&lt;p&gt;Cuando dos márgenes verticales se encuentran, &lt;strong&gt;no se suman&lt;/strong&gt;: se &lt;em&gt;colapsan&lt;/em&gt;, quedando solo el de mayor valor. Si un párrafo tiene &lt;code&gt;margin-bottom: 30px&lt;/code&gt; y el siguiente &lt;code&gt;margin-top: 20px&lt;/code&gt;, la separación entre ambos será de &lt;code&gt;30px&lt;/code&gt;, no &lt;code&gt;50px&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El colapso de márgenes solo ocurre con márgenes &lt;strong&gt;verticales&lt;/strong&gt; (arriba y abajo). Los márgenes horizontales (izquierda y derecha) nunca colapsan.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hay varias formas de impedir el colapso cuando no lo deseas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Aplicar &lt;code&gt;overflow: auto&lt;/code&gt; (o cualquier valor distinto de &lt;code&gt;visible&lt;/code&gt;) al contenedor.&lt;/li&gt;
&lt;li&gt;Añadir un &lt;code&gt;border&lt;/code&gt; o un &lt;code&gt;padding&lt;/code&gt; entre los dos márgenes.&lt;/li&gt;
&lt;li&gt;Usar un contenedor flotado, &lt;code&gt;inline-block&lt;/code&gt; o con posición absoluta/fija.&lt;/li&gt;
&lt;li&gt;Usar &lt;strong&gt;flexbox&lt;/strong&gt; o &lt;strong&gt;grid&lt;/strong&gt;: los márgenes entre ítems del layout no colapsan.&lt;/li&gt;
&lt;li&gt;Los elementos con &lt;code&gt;display: table-cell&lt;/code&gt; no tienen margen, así que no colapsan.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El modelo de caja deja de ser un misterio cuando interiorizas que &lt;code&gt;box-sizing&lt;/code&gt; controla la aritmética del tamaño, que la altura es orgánica por naturaleza y que los márgenes verticales colapsan. Activar &lt;code&gt;border-box&lt;/code&gt; de forma global y apoyarte en flexbox para el centrado elimina la mayoría de los problemas clásicos de maquetación.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 La siguiente entrega cubre los sistemas de &lt;strong&gt;layout&lt;/strong&gt;: &lt;code&gt;float&lt;/code&gt;, &lt;strong&gt;flexbox&lt;/strong&gt; y &lt;strong&gt;CSS Grid&lt;/strong&gt;, las herramientas con las que componemos la estructura completa de una página.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Futures, Awaitables y Errores Comunes en asyncio</title><link>https://blog.dacadev.com/python/asyncio/futures-awaitables-errores-comunes/</link><pubDate>Wed, 13 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/asyncio/futures-awaitables-errores-comunes/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Entiende qué son los futures y awaitables en asyncio, cómo medir el rendimiento de código asíncrono y los errores más comunes que bloquean el event loop en Python.</description><media:content url="https://blog.dacadev.com/images/python/asyncio/futures-awaitables/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#futures-un-valor-que-aún-no-existe"&gt;Futures: Un Valor que Aún No Existe&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#futures-en-la-práctica"&gt;Futures en la práctica&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-jerarquía-de-los-awaitables"&gt;La Jerarquía de los Awaitables&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#midiendo-el-tiempo-de-ejecución"&gt;Midiendo el Tiempo de Ejecución&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#uso-en-la-práctica"&gt;Uso en la práctica&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#errores-comunes-en-asyncio"&gt;Errores Comunes en &lt;code&gt;asyncio&lt;/code&gt;&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#1-ejecutar-código-cpu-bound-en-coroutines"&gt;1. Ejecutar código CPU-bound en coroutines&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#2-usar-apis-bloqueantes"&gt;2. Usar APIs bloqueantes&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#en-conclusión"&gt;En conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#referencias"&gt;Referencias&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En los artículos anteriores aprendimos a crear &lt;a href="https://blog.dacadev.com/python/asyncio/coroutines-async-await"



 


&gt;coroutines con async/await&lt;/a&gt; y ejecutar tasks concurrentes. En este artículo vamos a cerrar el modelo mental: entenderemos qué son los &lt;strong&gt;futures&lt;/strong&gt;, cómo se relacionan con tasks y coroutines a través de los &lt;strong&gt;awaitables&lt;/strong&gt;, y veremos cómo medir el rendimiento de nuestro código asíncrono. Para cerrar, hablaremos de los dos errores más comunes al trabajar con &lt;code&gt;asyncio&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="futures-un-valor-que-aún-no-existe"&gt;Futures: Un Valor que Aún No Existe&lt;/h2&gt;
&lt;p&gt;Un &lt;strong&gt;future&lt;/strong&gt; es un objeto de Python que representa un valor que esperamos obtener en algún momento, pero que &lt;strong&gt;todavía no tenemos&lt;/strong&gt;. Cuando se crea, un future está en estado &lt;em&gt;incompleto&lt;/em&gt;. Una vez que el valor llega, se establece con &lt;code&gt;set_result&lt;/code&gt; y el future pasa a estar &lt;em&gt;completado&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Future&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;my_future&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Future&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;¿Está completo? &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;my_future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;done&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;my_future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;set_result&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;42&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;¿Está completo? &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;my_future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;done&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Resultado: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;my_future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;result&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre class="mermaid"&gt;stateDiagram-v2
 [*] --&gt; Incompleto: Future()
 Incompleto --&gt; Completado: set_result(valor)
 Completado --&gt; [*]: result() → valor

 note right of Incompleto
 done() → False
 result() → InvalidStateError
 end note

 note right of Completado
 done() → True
 result() → valor
 end note
&lt;/pre&gt;

&lt;h3 id="futures-en-la-práctica"&gt;Futures en la práctica&lt;/h3&gt;
&lt;p&gt;En la mayoría de los casos no crearás futures directamente — &lt;code&gt;asyncio&lt;/code&gt; los gestiona internamente. Pero entender su mecánica es clave para comprender cómo funciona todo por dentro. Veamos un ejemplo donde un task establece el valor de un future después de un segundo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Future&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;hacer_peticion&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Future&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;future&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Future&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_task&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;establecer_valor&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;future&lt;/span&gt;)) &lt;span style="color:#7f848e"&gt;# 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;future&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;establecer_valor&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;future&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;set_result&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;42&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;future&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;hacer_peticion&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;¿Está completo? &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;done&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;valor&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;future&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;¿Está completo? &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;future&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;done&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;valor&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;main&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;Crea un task que configurará el valor del future.&lt;/li&gt;
&lt;li&gt;Espera 1 segundo antes de establecer el resultado.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;await&lt;/code&gt; pausa &lt;code&gt;main()&lt;/code&gt; hasta que el future reciba su valor.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant M as main()
 participant F as Future
 participant T as task: establecer_valor()

 M-&gt;&gt;F: hacer_peticion() → Future incompleto
 M-&gt;&gt;T: create_task(establecer_valor(future))
 M-&gt;&gt;F: await future
 Note over M: ⏸ PAUSE main()
 T-&gt;&gt;T: await asyncio.sleep(1)
 Note over T: ⏳ 1 segundo...
 T-&gt;&gt;F: set_result(42)
 Note over F: ✅ Completado
 F--&gt;&gt;M: ▶ RESUME main()
 Note over M: valor = 42
&lt;/pre&gt;

&lt;h2 id="la-jerarquía-de-los-awaitables"&gt;La Jerarquía de los Awaitables&lt;/h2&gt;
&lt;p&gt;Tanto las coroutines como los tasks pueden usarse con &lt;code&gt;await&lt;/code&gt;. ¿Qué tienen en común? Ambos son &lt;strong&gt;awaitables&lt;/strong&gt; — objetos que implementan el método &lt;code&gt;__await__&lt;/code&gt;, que es lo que Python necesita para poder usar la palabra clave &lt;code&gt;await&lt;/code&gt; sobre ellos.&lt;/p&gt;
&lt;p&gt;La relación entre estos conceptos forma una jerarquía clara:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A["Awaitable\n(__await__)"] --&gt; B["Coroutine"]
 A --&gt; C["Future"]
 C --&gt; D["Task"]

 style A fill:#8b5cf6,stroke:#5b21b6,color:#fff
 style B fill:#3b82f6,stroke:#1e40af,color:#fff
 style C fill:#f59e0b,stroke:#b45309,color:#fff
 style D fill:#10b981,stroke:#065f46,color:#fff
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Awaitable&lt;/strong&gt; es la clase base que define el protocolo &lt;code&gt;__await__&lt;/code&gt;. Todo lo que se pueda usar con &lt;code&gt;await&lt;/code&gt; es un awaitable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coroutine&lt;/strong&gt; es una función definida con &lt;code&gt;async def&lt;/code&gt;. Hereda de &lt;code&gt;Awaitable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future&lt;/strong&gt; representa un valor pendiente. También hereda de &lt;code&gt;Awaitable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Task&lt;/strong&gt; hereda de &lt;code&gt;Future&lt;/code&gt;. Es la combinación de un future y una coroutine: encapsula una coroutine y la ejecuta en el event loop, mientras que el future subyacente almacena el resultado cuando la coroutine termina.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Un &lt;strong&gt;Future&lt;/strong&gt; es &lt;em&gt;qué&lt;/em&gt; esperamos obtener. Un &lt;strong&gt;Task&lt;/strong&gt; es &lt;em&gt;cómo&lt;/em&gt; lo obtenemos (ejecutando una coroutine). Y &lt;strong&gt;Awaitable&lt;/strong&gt; es el contrato que ambos cumplen para que &lt;code&gt;await&lt;/code&gt; funcione.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="midiendo-el-tiempo-de-ejecución"&gt;Midiendo el Tiempo de Ejecución&lt;/h2&gt;
&lt;p&gt;Cuando trabajamos con código asíncrono, medir cuánto tarda cada operación es esencial para verificar que la concurrencia realmente funciona. La mejor forma de hacerlo es con un &lt;strong&gt;decorador&lt;/strong&gt; que registre el tiempo de inicio y fin de cada coroutine:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;functools&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Callable&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;async_timed&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;wrapper&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;func&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Callable&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Callable&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@functools.wraps&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;func&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;wrapped&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;&lt;span style="color:#e06c75"&gt;args&lt;/span&gt;, &lt;span style="color:#56b6c2"&gt;**&lt;/span&gt;&lt;span style="color:#e06c75"&gt;kwargs&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Any&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;starting &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;func&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; with args &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;args&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;kwargs&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;time&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;time&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;func&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;&lt;span style="color:#e06c75"&gt;args&lt;/span&gt;, &lt;span style="color:#56b6c2"&gt;**&lt;/span&gt;&lt;span style="color:#e06c75"&gt;kwargs&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;finally&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;end&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;time&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;time&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;total&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;end&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;-&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;finished &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;func&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; in &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;total&lt;/span&gt;&lt;span style="color:#98c379"&gt;:&lt;/span&gt;&lt;span style="color:#98c379"&gt;.4f&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; second(s)&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;wrapped&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;wrapper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="uso-en-la-práctica"&gt;Uso en la práctica&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#61afef"&gt;@async_timed&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;delay&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;delay_seconds&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;sleeping for &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;delay_seconds&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; second(s)&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;delay_seconds&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;finished sleeping for &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;delay_seconds&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; second(s)&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;delay_seconds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#61afef"&gt;@async_timed&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;task_one&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_task&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;delay&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;task_two&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_task&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;delay&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;3&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;task_one&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;task_two&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;main&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;starting &amp;lt;function main ...&amp;gt; with args () {}
starting &amp;lt;function delay ...&amp;gt; with args (2,) {}
starting &amp;lt;function delay ...&amp;gt; with args (3,) {}
finished &amp;lt;function delay ...&amp;gt; in 2.0032 second(s)
finished &amp;lt;function delay ...&amp;gt; in 3.0003 second(s)
finished &amp;lt;function main ...&amp;gt; in 3.0004 second(s)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;El output confirma lo que esperamos: ambos tasks corren concurrentemente. &lt;code&gt;delay(2)&lt;/code&gt; termina a los ~2 segundos, &lt;code&gt;delay(3)&lt;/code&gt; a los ~3, y &lt;code&gt;main()&lt;/code&gt; tarda ~3 segundos en total (no 5).&lt;/p&gt;
&lt;pre class="mermaid"&gt;gantt
 title Ejecución concurrente verificada con @async_timed
 dateFormat X
 axisFormat %s

 section delay(2)
 sleep(2) :a1, 0, 2

 section delay(3)
 sleep(3) :b1, 0, 3

 section main()
 Tiempo total :c1, 0, 3
&lt;/pre&gt;

&lt;h2 id="errores-comunes-en-asyncio"&gt;Errores Comunes en &lt;code&gt;asyncio&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Hay dos trampas frecuentes que pueden arruinar el rendimiento de una aplicación async. Ambas tienen la misma causa: &lt;strong&gt;bloquear el event loop&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="1-ejecutar-código-cpu-bound-en-coroutines"&gt;1. Ejecutar código CPU-bound en coroutines&lt;/h3&gt;
&lt;p&gt;Cuando tenemos funciones computacionalmente costosas (cálculos matemáticos, procesamiento de datos grandes), puede parecer buena idea envolverlas en tasks para ejecutarlas concurrentemente. Pero recuerda: &lt;code&gt;asyncio&lt;/code&gt; usa &lt;strong&gt;un solo hilo&lt;/strong&gt;. El GIL garantiza que solo una instrucción de bytecode se ejecute a la vez, así que el código CPU-bound bloqueará el event loop sin importar cuántos tasks crees.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A["Código CPU-bound\nen una coroutine"] --&gt;|"Bloquea el\nevent loop 🛑"| B["Otras tareas\nno pueden ejecutarse"]
 C["Solución"] --&gt; D["multiprocessing\no run_in_executor()"]

 style A fill:#ef4444,stroke:#991b1b,color:#fff
 style B fill:#ef4444,stroke:#991b1b,color:#fff
 style D fill:#10b981,stroke:#065f46,color:#fff
&lt;/pre&gt;

&lt;h3 id="2-usar-apis-bloqueantes"&gt;2. Usar APIs bloqueantes&lt;/h3&gt;
&lt;p&gt;El mismo problema ocurre al usar librerías de I/O que no son asíncronas. Librerías como &lt;code&gt;requests&lt;/code&gt; o funciones como &lt;code&gt;time.sleep&lt;/code&gt; bloquean el hilo principal. Cuando las llamas dentro de una coroutine, &lt;strong&gt;bloqueas el event loop completo&lt;/strong&gt; y ninguna otra coroutine puede ejecutarse.&lt;/p&gt;



&lt;div class="tab" data-tab-group=""&gt;
 &lt;ul class="tab-nav" data-tab-nav&gt;
 
 &lt;li
 class="tab-nav-item active"
 data-tab="bloqueante" tabindex="0"&gt;
 ❌ Bloqueante
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="no-bloqueante" tabindex="-1"&gt;
 ✅ No bloqueante
 &lt;/li&gt;
 
 &lt;/ul&gt;
 &lt;div class="tab-content" data-tab-content&gt;
 
 &lt;div
 class="tab-content-panel active"
 data-tab-panel="bloqueante"&gt;
 &lt;h4 id="no-uses-estas-funciones-dentro-de-coroutines"&gt;No uses estas funciones dentro de coroutines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requests.get()&lt;/code&gt; → bloquea el event loop&lt;/li&gt;
&lt;li&gt;&lt;code&gt;time.sleep()&lt;/code&gt; → bloquea el event loop&lt;/li&gt;
&lt;li&gt;Cualquier función de I/O síncrona&lt;/li&gt;
&lt;/ul&gt;

 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="no-bloqueante"&gt;
 &lt;h4 id="usa-las-alternativas-asíncronas"&gt;Usa las alternativas asíncronas&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aiohttp.org/"




 target="_blank"
 


&gt;&lt;code&gt;aiohttp&lt;/code&gt;&lt;/a&gt; → reemplazo async de &lt;code&gt;requests&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;asyncio.sleep()&lt;/code&gt; → cede control al event loop&lt;/li&gt;
&lt;li&gt;&lt;a href="https://magicstack.github.io/asyncpg/"




 target="_blank"
 


&gt;&lt;code&gt;asyncpg&lt;/code&gt;&lt;/a&gt; → cliente async de PostgreSQL&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Tinche/aiofiles"




 target="_blank"
 


&gt;&lt;code&gt;aiofiles&lt;/code&gt;&lt;/a&gt; → lectura/escritura async de archivos&lt;/li&gt;
&lt;/ul&gt;

 &lt;/div&gt;
 
 &lt;/div&gt;
&lt;/div&gt;





 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;Regla general:&lt;/strong&gt; cualquier función que realice I/O y no sea una coroutine, o que ejecute operaciones CPU costosas, debe considerarse bloqueante. Para CPU-bound, usa &lt;a href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor"




 target="_blank"
 


&gt;&lt;code&gt;loop.run_in_executor()&lt;/code&gt;&lt;/a&gt; con un &lt;code&gt;ProcessPoolExecutor&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="en-conclusión"&gt;En conclusión&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Un &lt;strong&gt;Future&lt;/strong&gt; representa un valor que aún no existe — se completa con &lt;code&gt;set_result&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Un &lt;strong&gt;Task&lt;/strong&gt; es un future + una coroutine: ejecuta la coroutine y almacena su resultado en el future subyacente.&lt;/li&gt;
&lt;li&gt;Todo lo que se pueda usar con &lt;code&gt;await&lt;/code&gt; es un &lt;strong&gt;Awaitable&lt;/strong&gt; — el contrato que unifica coroutines, futures y tasks.&lt;/li&gt;
&lt;li&gt;El decorador &lt;code&gt;@async_timed&lt;/code&gt; permite verificar que la concurrencia funciona midiendo tiempos reales.&lt;/li&gt;
&lt;li&gt;Los dos errores más comunes son ejecutar &lt;strong&gt;código CPU-bound&lt;/strong&gt; y usar &lt;strong&gt;APIs bloqueantes&lt;/strong&gt; dentro de coroutines — ambos bloquean el event loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="referencias"&gt;Referencias&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio-future.html"




 target="_blank"
 


&gt;Python &lt;code&gt;asyncio.Future&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio-task.html#asyncio.Task"




 target="_blank"
 


&gt;Python &lt;code&gt;asyncio.Task&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/reference/datamodel.html#awaitable-objects"




 target="_blank"
 


&gt;Python Data Model — Awaitables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://realpython.com/async-io-python/"




 target="_blank"
 


&gt;Real Python — Async IO in Python: A Complete Walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peps.python.org/pep-3156/"




 target="_blank"
 


&gt;PEP 3156 — Asynchronous IO Support Rebooted&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Coroutines y async/await: Tu Primer Código Asíncrono en Python</title><link>https://blog.dacadev.com/python/asyncio/coroutines-async-await/</link><pubDate>Tue, 12 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/asyncio/coroutines-async-await/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende a crear coroutines con async def, pausar la ejecución con await, usar asyncio.run y evitar la trampa del await secuencial en Python.</description><media:content url="https://blog.dacadev.com/images/python/asyncio/coroutines-async-await/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-una-coroutine"&gt;¿Qué es una Coroutine?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#creando-coroutines"&gt;Creando Coroutines&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejecutando-coroutines-con-asynciorun"&gt;Ejecutando Coroutines con &lt;code&gt;asyncio.run&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pausando-la-ejecución-con-await"&gt;Pausando la Ejecución con &lt;code&gt;await&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#simulando-operaciones-largas-con-asynciosleep"&gt;Simulando Operaciones Largas con &lt;code&gt;asyncio.sleep&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-trampa-del-await-secuencial"&gt;La Trampa del &lt;code&gt;await&lt;/code&gt; Secuencial&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-problema-visualizado"&gt;El problema visualizado&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cómo-logramos-concurrencia-real"&gt;¿Cómo logramos concurrencia real?&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#en-conclusión"&gt;En conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#referencias"&gt;Referencias&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En los artículos anteriores construimos la base teórica: &lt;a href="https://blog.dacadev.com/python/asyncio/fundamentos-asyncio"



 


&gt;concurrencia vs paralelismo&lt;/a&gt;, &lt;a href="https://blog.dacadev.com/python/asyncio/procesos-hilos-event-loop"



 


&gt;procesos, hilos, el GIL y el event loop&lt;/a&gt;. Ahora es momento de escribir código. En este artículo vamos a aprender a crear &lt;strong&gt;coroutines&lt;/strong&gt;, usar las palabras clave &lt;code&gt;async&lt;/code&gt; y &lt;code&gt;await&lt;/code&gt;, y entender exactamente qué pasa cuando pausamos y reanudamos la ejecución.&lt;/p&gt;
&lt;h2 id="qué-es-una-coroutine"&gt;¿Qué es una Coroutine?&lt;/h2&gt;
&lt;p&gt;Una coroutine es como una función normal de Python, pero con un superpoder: &lt;strong&gt;puede pausar su ejecución&lt;/strong&gt; cuando encuentra una operación que podría tardar (una petición de red, una lectura de disco, una espera). Mientras la coroutine está pausada, el event loop puede ejecutar otras tareas. Cuando la operación termina, la coroutine se &amp;ldquo;despierta&amp;rdquo; y continúa desde donde se detuvo.&lt;/p&gt;
&lt;p&gt;Esta capacidad de pausar y reanudar es lo que le da concurrencia a nuestra aplicación.&lt;/p&gt;
&lt;p&gt;Para trabajar con coroutines necesitamos dos palabras clave:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;async def&lt;/code&gt;&lt;/strong&gt; → define una coroutine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;await&lt;/code&gt;&lt;/strong&gt; → pausa la coroutine hasta que la operación esperada termine.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="creando-coroutines"&gt;Creando Coroutines&lt;/h2&gt;
&lt;p&gt;Crear una coroutine es casi idéntico a crear una función normal. La única diferencia es usar &lt;code&gt;async def&lt;/code&gt; en lugar de &lt;code&gt;def&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;mi_coroutine&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;¡Hola mundo!&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;Llamar a una coroutine no la ejecuta.&lt;/strong&gt; Solo produce un objeto coroutine. Para ejecutarla, necesitas un event loop.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# ❌ Esto NO ejecuta la coroutine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;mi_coroutine&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# Retorna un objeto coroutine, no imprime nada&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# ✅ Esto SÍ la ejecuta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;mi_coroutine&lt;/span&gt;()) &lt;span style="color:#7f848e"&gt;# Imprime: ¡Hola mundo!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ejecutando-coroutines-con-asynciorun"&gt;Ejecutando Coroutines con &lt;code&gt;asyncio.run&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;asyncio.run&lt;/code&gt; es el &lt;strong&gt;punto de entrada principal&lt;/strong&gt; de cualquier aplicación asyncio. Veamos un ejemplo concreto:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;sumar_uno&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;numero&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;numero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;resultado&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;sumar_uno&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;resultado&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;asyncio.run&lt;/code&gt; hace varias cosas por nosotros:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Crea&lt;/strong&gt; un event loop nuevo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejecuta&lt;/strong&gt; la coroutine que le pasamos hasta que se completa.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retorna&lt;/strong&gt; el resultado de la coroutine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limpia&lt;/strong&gt; cualquier tarea pendiente y cierra el event loop.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A["asyncio.run(coroutine)"] --&gt; B["Crea el\nEvent Loop"]
 B --&gt; C["Ejecuta la\ncoroutine"]
 C --&gt; D["Retorna\nel resultado"]
 D --&gt; E["Cierra el\nEvent Loop"]

 style A fill:#3b82f6,stroke:#1e40af,color:#fff
 style C fill:#10b981,stroke:#065f46,color:#fff
 style E fill:#64748b,stroke:#334155,color:#fff
&lt;/pre&gt;





 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;asyncio.run&lt;/code&gt; está diseñado para ejecutarse &lt;strong&gt;una sola vez&lt;/strong&gt; como entrada principal de tu aplicación. Esa única coroutine debería encargarse de lanzar todas las demás tareas.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="pausando-la-ejecución-con-await"&gt;Pausando la Ejecución con &lt;code&gt;await&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;El verdadero poder de asyncio está en &lt;code&gt;await&lt;/code&gt;. Esta palabra clave hace dos cosas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ejecuta&lt;/strong&gt; la coroutine que le sigue (a diferencia de llamarla directamente, que solo crea el objeto).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pausa&lt;/strong&gt; la coroutine contenedora hasta que la coroutine esperada retorne un resultado.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cuando la coroutine esperada termina, la coroutine contenedora se &amp;ldquo;despierta&amp;rdquo; y puede usar el resultado.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;obtener_saludo&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;¡Hola desde una coroutine!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;saludo&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;obtener_saludo&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# Pausa main() hasta obtener el resultado&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;saludo&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;main&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="simulando-operaciones-largas-con-asynciosleep"&gt;Simulando Operaciones Largas con &lt;code&gt;asyncio.sleep&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Para simular una operación de I/O de larga duración (como una petición HTTP o una consulta a base de datos), podemos usar &lt;code&gt;asyncio.sleep&lt;/code&gt;. Esta función pausa la coroutine por el número de segundos indicado, cediendo el control al event loop.&lt;/p&gt;
&lt;p&gt;Veamos un ejemplo más completo con una función auxiliar &lt;code&gt;delay&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;delay&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;seconds&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Esperando &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;seconds&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; segundo(s)...&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;seconds&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;¡Espera de &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;seconds&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; segundo(s) completada!&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Esperé &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;seconds&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; segundo(s)&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="la-trampa-del-await-secuencial"&gt;La Trampa del &lt;code&gt;await&lt;/code&gt; Secuencial&lt;/h2&gt;
&lt;p&gt;Ahora veamos un error muy común al empezar con asyncio. Considera este código:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;sumar_uno&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;numero&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;numero&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;mensaje_hola_mundo&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;¡Hola Mundo!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;mensaje&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;mensaje_hola_mundo&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# Pausa 1 segundo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;uno_mas_uno&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;sumar_uno&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# Ejecuta después de la pausa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;uno_mas_uno&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;mensaje&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;main&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cuando ejecutamos este código, &lt;strong&gt;pasa 1 segundo&lt;/strong&gt; antes de que se impriman ambos resultados. Pero &lt;code&gt;sumar_uno(1)&lt;/code&gt; es instantánea — ¿por qué espera?&lt;/p&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;await&lt;/code&gt; pausa toda la coroutine contenedora.&lt;/strong&gt; No se ejecuta ningún otro código dentro de &lt;code&gt;main()&lt;/code&gt; hasta que la expresión &lt;code&gt;await&lt;/code&gt; retorne un valor. Como &lt;code&gt;mensaje_hola_mundo()&lt;/code&gt; tarda 1 segundo, &lt;code&gt;main()&lt;/code&gt; queda pausada ese segundo completo antes de siquiera llegar a &lt;code&gt;sumar_uno(1)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;El siguiente diagrama muestra exactamente qué pasa en cada momento:&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant EL as Event Loop
 participant M as main()
 participant HW as mensaje_hola_mundo()
 participant AO as sumar_uno(1)

 EL-&gt;&gt;M: ▶ RUN main()
 Note over M: await mensaje_hola_mundo()
 M-&gt;&gt;HW: ▶ RUN mensaje_hola_mundo()
 HW-&gt;&gt;HW: await sleep(1)
 Note over M: ⏸ PAUSE main()
 Note over HW: ⏸ PAUSE mensaje_hola_mundo()
 Note over EL: ⏳ Pasa 1 segundo...
 EL-&gt;&gt;HW: ▶ RESUME mensaje_hola_mundo()
 Note over HW: return '¡Hola Mundo!'
 HW--&gt;&gt;M: ▶ RESUME main()
 Note over M: mensaje = '¡Hola Mundo!'
 Note over M: await sumar_uno(1)
 M-&gt;&gt;AO: ▶ RUN sumar_uno(1)
 Note over AO: return 1 + 1
 AO--&gt;&gt;M: ▶ RESUME main()
 Note over M: uno_mas_uno = 2
 Note over M: print() resultados
&lt;/pre&gt;

&lt;h3 id="el-problema-visualizado"&gt;El problema visualizado&lt;/h3&gt;
&lt;p&gt;El flujo de ejecución es completamente &lt;strong&gt;secuencial&lt;/strong&gt;, a pesar de usar &lt;code&gt;async/await&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="mermaid"&gt;gantt
 title Ejecución secuencial — Sin concurrencia real
 dateFormat X
 axisFormat %s

 section main()
 await mensaje_hola_mundo() :a1, 0, 10
 await sumar_uno(1) :a2, 10, 11
 print() resultados :a3, 11, 12
&lt;/pre&gt;

&lt;p&gt;Lo que &lt;em&gt;queremos&lt;/em&gt; es que &lt;code&gt;sumar_uno(1)&lt;/code&gt; se ejecute &lt;strong&gt;mientras&lt;/strong&gt; &lt;code&gt;mensaje_hola_mundo()&lt;/code&gt; espera su segundo de delay. Pero con &lt;code&gt;await&lt;/code&gt; secuencial eso no es posible — cada &lt;code&gt;await&lt;/code&gt; bloquea la coroutine hasta completarse.&lt;/p&gt;
&lt;h3 id="cómo-logramos-concurrencia-real"&gt;¿Cómo logramos concurrencia real?&lt;/h3&gt;
&lt;p&gt;Para ejecutar múltiples coroutines de forma concurrente necesitamos herramientas como &lt;code&gt;asyncio.gather&lt;/code&gt; o &lt;code&gt;asyncio.create_task&lt;/code&gt;. Un adelanto rápido:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# ✅ Ambas coroutines corren concurrentemente&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;mensaje&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;uno_mas_uno&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;gather&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;mensaje_hola_mundo&lt;/span&gt;(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;sumar_uno&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;uno_mas_uno&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;mensaje&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Con &lt;code&gt;gather&lt;/code&gt;, el event loop puede ejecutar &lt;code&gt;sumar_uno(1)&lt;/code&gt; mientras &lt;code&gt;mensaje_hola_mundo()&lt;/code&gt; está pausada esperando su &lt;code&gt;sleep&lt;/code&gt;. El tiempo total se mantiene en ~1 segundo en lugar de sumar ambos tiempos.&lt;/p&gt;
&lt;pre class="mermaid"&gt;gantt
 title Ejecución concurrente — Con asyncio.gather
 dateFormat X
 axisFormat %s

 section mensaje_hola_mundo()
 await sleep(1) :a1, 0, 10

 section sumar_uno(1)
 return 1 + 1 :a2, 0, 1

 section main()
 print() resultados :a3, 10, 11
&lt;/pre&gt;

&lt;h2 id="en-conclusión"&gt;En conclusión&lt;/h2&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A["async def"] --&gt;|"Define"| B["Coroutine"]
 B --&gt;|"Se ejecuta con"| C["asyncio.run()"]
 B --&gt;|"Se pausa con"| D["await"]
 D --&gt;|"Cede control al"| E["Event Loop"]
 E --&gt;|"Cuando I/O completa"| F["Reanuda la coroutine"]
 C --&gt;|"Crea y gestiona"| E

 style A fill:#8b5cf6,stroke:#5b21b6,color:#fff
 style B fill:#3b82f6,stroke:#1e40af,color:#fff
 style D fill:#f59e0b,stroke:#b45309,color:#fff
 style E fill:#10b981,stroke:#065f46,color:#fff
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;async def&lt;/code&gt;&lt;/strong&gt; define una coroutine — una función que puede pausarse.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;await&lt;/code&gt;&lt;/strong&gt; pausa la coroutine actual hasta que la operación esperada termine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;asyncio.run&lt;/code&gt;&lt;/strong&gt; crea el event loop y ejecuta la coroutine principal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;asyncio.sleep&lt;/code&gt;&lt;/strong&gt; simula operaciones de I/O de larga duración.&lt;/li&gt;
&lt;li&gt;Usar &lt;code&gt;await&lt;/code&gt; de forma secuencial &lt;strong&gt;no da concurrencia&lt;/strong&gt; — para eso necesitamos &lt;code&gt;asyncio.gather&lt;/code&gt; o &lt;code&gt;asyncio.create_task&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="referencias"&gt;Referencias&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio-task.html"




 target="_blank"
 


&gt;Python &lt;code&gt;asyncio&lt;/code&gt; — Documentación Oficial: Coroutines and Tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peps.python.org/pep-0492/"




 target="_blank"
 


&gt;PEP 492 — Coroutines with async and await syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://realpython.com/async-io-python/"




 target="_blank"
 


&gt;Real Python — Async IO in Python: A Complete Walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Tipado básico en Python</title><link>https://blog.dacadev.com/python/tipado/02-tipado-basico/</link><pubDate>Sat, 10 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/02-tipado-basico/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende a aplicar tipos en Python de manera efectiva. Descubre cómo agregar tipado en variables, colecciones, y funciones en Python. Incluye ejemplos prácticos y recomendaciones según la versión de Python.</description><media:content url="https://blog.dacadev.com/images/python/typing/bases/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#tipos-buitl-in-in-python"&gt;Tipos Buitl-in in Python&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipado-en-colecciones"&gt;Tipado en colecciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#combinación-de-tipos-en-python"&gt;Combinación de Tipos en Python&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#definir-más-de-un-tipo"&gt;Definir Más de un Tipo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#valores-opcionales-o-none"&gt;Valores Opcionales o &lt;code&gt;None&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#definir-valores-fijos"&gt;Definir Valores Fijos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#definir-tipos-personalizados"&gt;Definir Tipos Personalizados&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#datos-io-en-python"&gt;Datos IO en Python&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;p&gt;Este artículo es parte de una serie que explica el tipado en Python. A continuación, puedes ver la recopilación de todos los posts de la serie.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.dacadev.com/python/tipado/serie-de-tipado" class="btn btn-outline-primary " rel="" &gt;Ver serie&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Agregar tipos en Python es muy sencillo y tiene una sintaxis similar a otros lenguajes como &lt;em&gt;Typescript&lt;/em&gt;. &lt;strong&gt;No es obligatorio&lt;/strong&gt; aplicar tipado en cada pieza de código, lo que permite agregarlo de manera gradual. Además, agregar o no tipos no afectará el comportamiento del código.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La posibilidad de agregar tipado en Python está disponible desde la versión &lt;strong&gt;3.5&lt;/strong&gt;. Desde entonces, se han añadido nuevas características y mejoras.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tipos-buitl-in-in-python"&gt;Tipos Buitl-in in Python&lt;/h2&gt;
&lt;p&gt;Los tipos &lt;em&gt;built-in&lt;/em&gt; son aquellos que vienen por defecto en Python, como &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, entre otros.&lt;/p&gt;
&lt;p&gt;Para agregar tipado a una variable, simplemente añade &lt;code&gt;:&lt;/code&gt; después del nombre de la variable y luego especifica el tipo de dato. La sintaxis es:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;variable&amp;gt;: &amp;lt;type&amp;gt; = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;n&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;f&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;c&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;complex&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&lt;span style="color:#e06c75"&gt;j&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;s&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;bytes&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;b&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;bytes&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;t&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;v&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el anterior ejemplo estamos definiendo que cada una de las variables solo van a manejar un tipo de datos a lo largo de vida en el programa.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Recuerda que el agregar el tipo de dato no afecta el comportamiento del código, es solo una ayuda para el programador, analizadores de código estáticos e IDEs.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tipado-en-colecciones"&gt;Tipado en colecciones&lt;/h2&gt;
&lt;p&gt;Para colecciones como &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, la sintaxis es similar a la de las variables simples. salvo que podemos definir o nor el tipo de variable que cada variable va a contener. es decir que tenemos dos tipos de sintaxis que podemos utilizar.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;variable&amp;gt;: &amp;lt;collection&amp;gt; = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;variable&amp;gt;: &amp;lt;collection&amp;gt;[&amp;lt;type&amp;gt;...] = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En la primera opción estamos definiendo que la variable va a ser de tipo &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; y en la segunda opción estamos definiendo que la variable va a ser de tipo &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; y que va a contener un tipo de dato especifico. Veamos como se aplica esto en algunos ejemplos, para ello es importante tener en cuenta la versión de Python que estás utilizando.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python 3.5 a 3.8:&lt;/strong&gt; Es necesario importar los tipos de la librería &lt;code&gt;typing&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;List&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Set&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Tuple&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Dict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;l&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;List&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;s&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Set&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {&lt;span style="color:#98c379"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;t&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Tuple&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Python&amp;#34;&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;d&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {&lt;span style="color:#98c379"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python 3.9 y posteriores:&lt;/strong&gt; Puedes utilizar la sintaxis estándar sin importar &lt;code&gt;typing&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;l&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;s&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;set&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {&lt;span style="color:#98c379"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;t&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Python&amp;#34;&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;d&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {&lt;span style="color:#98c379"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En los ejemplos anteriores podemos observar que estamos definiendo un tipo de colección diferente por cada varibale y cabe destacar que en el caso de las colecciones podemos definir el tipo de dato que va a contener cada una de las variables, debes tener en cuenta que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;para &lt;code&gt;list&lt;/code&gt; y &lt;code&gt;set&lt;/code&gt; se utiliza el tipo de dato que va a contener entre corchetes &lt;code&gt;[]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;para &lt;code&gt;tuple&lt;/code&gt; se define el tipo de dato y la posición dentro de la tupla entre corchetes &lt;code&gt;[]&lt;/code&gt;, es decir que en el ejemplo se espera que sea una tupla de tres elementos que estaran en el siguiente orden &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;para &lt;code&gt;dict&lt;/code&gt; se define el tipo de dato que va a contener la llave y el valor entre corchetes &lt;code&gt;[]&lt;/code&gt;, es decir que en el ejemplo se espera que sea un diccionario con llaves de tipo &lt;code&gt;str&lt;/code&gt; y valores de tipo &lt;code&gt;bool&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="combinación-de-tipos-en-python"&gt;Combinación de Tipos en Python&lt;/h2&gt;
&lt;p&gt;En algunos casos, es necesario que las variables puedan contener más de un tipo de dato o incluso que puedan ser opcionales. Para ello se han definido diversas estrategias para alcanzar esta funcionalidad&lt;/p&gt;
&lt;h3 id="definir-más-de-un-tipo"&gt;Definir Más de un Tipo&lt;/h3&gt;
&lt;p&gt;Utiliza el carácter &lt;code&gt;|&lt;/code&gt; para definir más de un tipo de dato en una variable, este carácter actúa como un &lt;code&gt;OR&lt;/code&gt; lógico:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;one&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Para versiones anteriores a Python 3.9, importa &lt;code&gt;Union&lt;/code&gt; de &lt;code&gt;typing&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;one&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="valores-opcionales-o-none"&gt;Valores Opcionales o &lt;code&gt;None&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Para definir que un valor es opcional, añade &lt;code&gt;None&lt;/code&gt; como parte de los tipos posibles:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Para versiones anteriores a Python 3.9, utiliza &lt;code&gt;Optional&lt;/code&gt; o &lt;code&gt;Union&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Opción 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Optional&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Opción 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="definir-valores-fijos"&gt;Definir Valores Fijos&lt;/h3&gt;
&lt;p&gt;Si deseas restringir los valores que puede tomar una variable, usa &lt;code&gt;Literal&lt;/code&gt; de &lt;code&gt;typing&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;cards&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;clubs&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;diamonds&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;hearts&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;spades&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;cards&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;clubs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="definir-tipos-personalizados"&gt;Definir Tipos Personalizados&lt;/h2&gt;
&lt;p&gt;EN Python asi como con las variables es posible definir tipos personalizados, para simplificar la lectura del código o incluso para darle un mejor entendimiento al código. en la siguiente pieza de código podemos ver esta funcionalidad.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;UserType&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;ID&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;PersonalData&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;User&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;ID&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;PersonalData&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;UserType&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;UserUgly&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Como podemos observa en el ejemplo anterior estamos separando nuestra definición de tipos en otros tipos para facilitar la lectura de nuestro código, en el caso de &lt;code&gt;User&lt;/code&gt; y &lt;code&gt;UserUgly&lt;/code&gt; estamos definiendo un tipo de dato que va a ser una tupla que va a contener un &lt;code&gt;ID&lt;/code&gt;, &lt;code&gt;PersonalData&lt;/code&gt; y &lt;code&gt;UserType&lt;/code&gt; y en el caso de &lt;code&gt;UserUgly&lt;/code&gt; estamos definiendo el mismo tipo de dato pero de una manera menos legible.&lt;/p&gt;
&lt;p&gt;si escribieramos el mismo código para versiones anteriores a Python 3.9, el código se vería de la siguiente manera:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;UserType&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;ID&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;PersonalData&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Optional&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;User&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;ID&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;PersonalData&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;UserType&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="datos-io-en-python"&gt;Datos IO en Python&lt;/h2&gt;
&lt;p&gt;Cuando trabajes con datos de entrada/salida, como la lectura de archivos, usa el tipo &lt;code&gt;IO&lt;/code&gt; de &lt;code&gt;typing&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;IO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;text_file&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;IO&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# text, json, xml, html...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;bin_file&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;IO&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;bytes&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# jpeg, png, pdf, mp3...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El tipo &lt;code&gt;IO&lt;/code&gt; es un tipo genérico que se utiliza para representar objetos que son streams de entrada o salida, como archivos y sockets, y solo admite tipos de datos &lt;code&gt;str&lt;/code&gt; y &lt;code&gt;bytes&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;p&gt;En este artículo, hemos cubierto las nociones básicas sobre cómo agregar tipos a tus variables en Python. En el próximo artículo, exploraremos cómo agregar tipos a funciones y métodos.&lt;/p&gt;
&lt;!-- &lt;br /&gt;&lt;br /&gt;






 
 
 
 
 
 
 
 
 
 


&lt;a href="https://blog.dacadev.com/python/tipado/tipado-de-funciones-y-metodos" class="btn btn-outline-primary " rel="" &gt;Siguiente artículo&lt;/a&gt;
 --&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>GitHub Copilot: Beneficios, Desventajas y Precauciones</title><link>https://blog.dacadev.com/programacion/github-copilot-beneficios-desventajas-precauciones/</link><pubDate>Mon, 27 May 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/github-copilot-beneficios-desventajas-precauciones/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Descubre cómo GitHub Copilot puede revolucionar tu forma de programar. Aprende sobre sus funcionalidades, beneficios, desventajas y precauciones en esta guía completa.</description><media:content url="https://blog.dacadev.com/images/programming/github-copilot-beneficios-desventajas-precauciones/banner.jpg" medium="image" type="image/jpeg"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-github-copilot"&gt;¿Qué es GitHub Copilot?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#debo-preocuparme-por-el-manejo-de-datos"&gt;¿Debo preocuparme por el manejo de datos?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cuáles-son-los-alcances-de-copilot"&gt;¿Cuáles son los alcances de Copilot?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#es-acertado-copilot-en-sus-predicciones"&gt;¿Es acertado Copilot en sus predicciones?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#beneficios-de-usar-copilot"&gt;Beneficios de usar Copilot&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#precauciones-y-desventajas-de-copilot"&gt;Precauciones y desventajas de Copilot&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;p&gt;Este artículo nace como una iniciativa para centralizar el conocimiento que he adquirido en el manejo de la herramienta de &lt;strong&gt;GitHub Copilot&lt;/strong&gt; gracias a su uso diario, cursos y consejos que he encontrado en diversos recursos.&lt;/p&gt;
&lt;p&gt;La herramienta la puedes encontrar en el siguiente enlace: &lt;a href="https://github.com/features/copilot"




 target="_blank"
 


&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; es una herramienta de inteligencia artificial que nos ofrece toda la potencia de los modelos de lenguaje a gran escala (LLM, por sus siglas en inglés) enfocada específicamente en el campo del desarrollo de software y programación. Es una herramienta que ha revolucionado la manera de escribir código y aún tiene mucho más por aportar. Veamos algunas de sus funcionalidades y beneficios, así como desventajas y riesgos de usar esta herramienta.&lt;/p&gt;
&lt;h2 id="qué-es-github-copilot"&gt;¿Qué es GitHub Copilot?&lt;/h2&gt;
&lt;p&gt;Mi definición de lo que es &lt;strong&gt;Copilot&lt;/strong&gt; sería:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; es una herramienta de programación de pair programming que extiende las habilidades de los desarrolladores permitiendo enfocarse en el diseño, delegando la “carpintería” al copiloto.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Adicionalmente, si queremos ser un poco más técnicos al respecto y definir qué es &lt;strong&gt;Copilot&lt;/strong&gt; técnicamente, debemos decir que &lt;strong&gt;Copilot&lt;/strong&gt; trabaja sobre las mismas bases de los LLMs como ChatGPT, con la salvedad de que fue afinado para que su enfoque sea 100% en la escritura de código.&lt;/p&gt;
&lt;p&gt;Los datos usados para ajustar el modelo que alimenta a &lt;strong&gt;GitHub Copilot&lt;/strong&gt; fueron todos los repositorios públicos que se encuentran en GitHub, siendo esta la plataforma más usada para alojar proyectos alrededor del mundo. Esto significa que el conjunto de datos de entrenamiento es inmenso y muy completo.&lt;/p&gt;
&lt;p&gt;Por último, como &lt;strong&gt;Copilot&lt;/strong&gt; está basado en la tecnología de los LLMs, en general lo que busca es predecir, a partir de probabilidades, cuál sería el código que seguiría a medida que vas escribiendo.&lt;/p&gt;
&lt;h2 id="debo-preocuparme-por-el-manejo-de-datos"&gt;¿Debo preocuparme por el manejo de datos?&lt;/h2&gt;
&lt;p&gt;Una de las principales dudas al momento de usar &lt;strong&gt;Copilot&lt;/strong&gt;, incluso podría pensar que la primera duda, es ¿&lt;strong&gt;Copilot&lt;/strong&gt; usará mis datos y mi código para futuras sugerencias? o en palabras más simples ¿&lt;strong&gt;Copilot&lt;/strong&gt; va a robar mi código?&lt;/p&gt;
&lt;p&gt;La respuesta es un NO rotundo. &lt;strong&gt;Copilot&lt;/strong&gt; no usará tu código o el código generado con la herramienta para reentrenar el modelo, ya que, como mencioné antes, esta herramienta solo es entrenada con datos públicos que se obtienen de los repositorios públicos de GitHub.&lt;/p&gt;
&lt;p&gt;Además, el código generado a partir de &lt;strong&gt;Copilot&lt;/strong&gt; no es alojado para realizar una futura realimentación del modelo, por lo que puedes estar seguro de la privacidad de tu código y de tu negocio a fin de cuentas.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este punto debo mencionar algo y es la propiedad intelectual. Puede que &lt;strong&gt;Copilot&lt;/strong&gt; no respete la propiedad intelectual si esta es en un repositorio público, por lo que si quieres tener este tipo de protección y a la vez tener un código abierto, es mejor asesorarte.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="cuáles-son-los-alcances-de-copilot"&gt;¿Cuáles son los alcances de Copilot?&lt;/h2&gt;
&lt;p&gt;Como mencionamos antes, &lt;strong&gt;Copilot&lt;/strong&gt; es tu compañero de programación en pareja, esto significa que te ayudará a escribir código brindando sugerencias durante la escritura del mismo, pero aquí puede surgir una pregunta muy importante: &lt;strong&gt;¿Puede Copilot ayudarme sin importar el lenguaje?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;La respuesta a esta pregunta es ambigua, sí y no. Es un sí porque recuerda que el modelo fue entrenado usando todo el código público alojado en GitHub, y entre estos encontramos una diversidad inmensa de lenguajes, frameworks, estilos, prácticas, etc. Sin embargo, también debemos tener en cuenta que los lenguajes más populares como JavaScript o Python son los que más proyectos tienen alojados en GitHub, lo que significa que el modelo aprendió más de estos lenguajes, haciéndolo mucho más eficiente para estos tipos de lenguajes o frameworks.&lt;/p&gt;
&lt;p&gt;Si intentas utilizar &lt;strong&gt;Copilot&lt;/strong&gt; con algún lenguaje que no es tan popular como COBOL, es posible que &lt;strong&gt;Copilot&lt;/strong&gt; no haga un muy buen trabajo, pero lo intentará.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Si tienes miedo de que la IA te pueda arrebatar el trabajo, tiene sentido buscar aquello en lo que la IA no es realmente buena&amp;hellip; ¿aún? Esto es solo una opinión que podría ser una buena discusión, ¿qué opinas?&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="es-acertado-copilot-en-sus-predicciones"&gt;¿Es acertado Copilot en sus predicciones?&lt;/h2&gt;
&lt;p&gt;Esta es una pregunta que muchas personas se hacen, sin importar el nivel de experiencia que tengan, y volviendo a retomar la idea de antes, sus predicciones mejorarán a medida que sea usado para escribir código de lenguajes o contextos populares, ya que tendrá más conocimiento de dónde echar mano.&lt;/p&gt;
&lt;p&gt;Dado lo anterior, es MUY IMPORTANTE que tú, como desarrollador, supervises siempre el resultado de &lt;strong&gt;Copilot&lt;/strong&gt;. No importa qué tan sencillo o simple sea, hazlo como una nueva práctica para el uso de esta herramienta ya que &lt;strong&gt;Copilot&lt;/strong&gt; solo predice, no piensa realmente&amp;hellip; ¿aún? 🤔&lt;/p&gt;
&lt;p&gt;Aquí quiero hacer un énfasis que es mandatorio, y es el de la supervisión. Tu responsabilidad como programador es supervisar el resultado de &lt;strong&gt;Copilot&lt;/strong&gt;, y esto se puede hacer eficientemente solamente si:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conoces la tecnología, lenguaje, frameworks, etc. que &lt;strong&gt;Copilot&lt;/strong&gt; te está ayudando a construir.&lt;/li&gt;
&lt;li&gt;Entiendes lo que estás construyendo y el propósito, la lógica de negocio.&lt;/li&gt;
&lt;li&gt;Entiendes a nivel macro el impacto de tu trabajo, &lt;strong&gt;Copilot&lt;/strong&gt; te ayudará con lo micro.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Debes ser siempre consciente de lo que estás construyendo, siempre recuérdalo porque con el uso de &lt;strong&gt;Copilot&lt;/strong&gt; es fácil caer en la tentación de dejar pasar algunas cosas.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="beneficios-de-usar-copilot"&gt;Beneficios de usar Copilot&lt;/h2&gt;
&lt;p&gt;Hablemos ahora de cuáles son los beneficios de usar &lt;strong&gt;Copilot&lt;/strong&gt;. ¡Hay muchos!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Incrementa la productividad, ya que no gastarás tiempo escribiendo y reescribiendo código, sobre todo si son piezas pequeñas pero tediosas.&lt;/li&gt;
&lt;li&gt;Reduce los errores en el código, aunque debamos supervisar el resultado de &lt;strong&gt;Copilot&lt;/strong&gt;, este siempre nos ayudará a reducir errores comunes como los typos o referencias mal realizadas.&lt;/li&gt;
&lt;li&gt;Permite tener una gran diversidad de código, ya que puedes pedirle a &lt;strong&gt;Copilot&lt;/strong&gt; que te dé no solo una, sino más sugerencias, permitiéndonos ahondar en múltiples estilos o diseños de código.&lt;/li&gt;
&lt;li&gt;Soporta múltiples lenguajes, con mejor rendimiento en unos más que en otros.&lt;/li&gt;
&lt;li&gt;Te permite aprender y desarrollar al mismo tiempo. Cuando &lt;strong&gt;Copilot&lt;/strong&gt; te ayuda a escribir código, puede implementar técnicas o ideas nuevas para ti y te permitirá aprender de ellas. Para ello, debes ser consciente y supervisar el resultado, no confíes 100% en su respuesta. Valida en la documentación o en recursos de confianza.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copilot&lt;/strong&gt; se ajustará a tu tipo de código. A medida que lo uses, entenderá cuál es el estilo de código en base a lo ya escrito en el proyecto. Tú lo orientas en base a cómo escribas código. Esto significa que si cambias de proyecto y este tiene otras reglas, &lt;strong&gt;Copilot&lt;/strong&gt; se adaptará. Él no aprende de ti.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="precauciones-y-desventajas-de-copilot"&gt;Precauciones y desventajas de Copilot&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Su precisión es variable dependiendo del contexto del prompt y del mismo código que tienes en ese archivo. Esto depende del tiempo de trabajo en el proyecto con &lt;strong&gt;Copilot&lt;/strong&gt;, los archivos abiertos y el código de referencia.&lt;/li&gt;
&lt;li&gt;Riesgos de seguridad potenciales. Debes supervisar el resultado, sobre todo si trabajas con partes sensibles del código como SQL, ORMs, código de lógica de negocio, etc. Valida el código que propone &lt;strong&gt;Copilot&lt;/strong&gt; y, si no lo conocías, valida su uso en la documentación o un recurso de confianza.&lt;/li&gt;
&lt;li&gt;Depender demasiado de la herramienta. Para que esto no suceda, debes conocer bien la tecnología, lenguaje y sistema que estás construyendo, para tener el criterio y confianza de que lo que estás haciendo lo podrías hacer sin ayuda de &lt;strong&gt;Copilot&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Una “desventaja” es que tiene un costo, no tiene opción de uso gratuito o similar, y es más costoso a medida que se implementa en organizaciones. Esto, en algunos casos como personas/empresas que están empezando, puede ser un valor difícil de asumir. Debes tener claro el valor que agrega en el equipo y ese gasto adicional incluirlo en tus cuentas.&lt;/li&gt;
&lt;li&gt;Límite en el contexto de la herramienta. Esta es una desventaja de los LLMs en general y, aunque es algo que está en constante mejora, es muy difícil (por lo menos hasta ahora) incluir todo un proyecto en el contexto de un LLM y adicionalmente compartir qué es lo que se busca hacer. Por lo que para tareas muy grandes con un código fuente enorme, tiende a no ser tan preciso.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; ha revolucionado la forma en que los desarrolladores escriben código, ofreciendo beneficios significativos como el aumento de la productividad y la reducción de errores. Sin embargo, es crucial supervisar sus sugerencias y estar consciente de sus limitaciones y riesgos. A medida que la tecnología avanza, &lt;strong&gt;Copilot&lt;/strong&gt; seguirá mejorando, pero siempre será necesario el criterio humano para garantizar la calidad y la seguridad del código.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este artículo se actualiza periódicamente conforme evolucionan las funcionalidades de &lt;strong&gt;GitHub Copilot&lt;/strong&gt;. Si tienes experiencias o consejos adicionales, no dudes en compartirlos a través de la &lt;a href="https://blog.dacadev.com/contacto"



 


&gt;página de contacto&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Aprovecha al Máximo go.work y go.mod en Golang</title><link>https://blog.dacadev.com/golang/go-work-y-go-mod/</link><pubDate>Fri, 24 May 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/golang/go-work-y-go-mod/</guid><dc:creator>Dacadev</dc:creator><category>golang</category><description>Descubre cómo utilizar y optimizar el manejo de módulos y workspaces en Golang para mejorar tu flujo de desarrollo.</description><media:content url="https://blog.dacadev.com/images/golang/go-work-and-go-mod/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-son-los-módulos-de-golang"&gt;¿Qué son los módulos de Golang?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cómo-interactuar-con-los-módulos-de-golang"&gt;¿Cómo interactuar con los módulos de Golang?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#qué-es-go-workspace"&gt;¿Qué es Go Workspace?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cómo-usar-gowork"&gt;¿Cómo usar go.work?&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo, aprenderás a usar los módulos de &lt;strong&gt;Golang&lt;/strong&gt;, qué son y cómo usarlos. Además, complementaremos el uso de múltiples módulos en un proyecto con la ayuda de &lt;code&gt;go.work&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-son-los-módulos-de-golang"&gt;¿Qué son los módulos de Golang?&lt;/h2&gt;
&lt;p&gt;Dentro del ecosistema de Golang para gestionar las dependencias de un proyecto, tenemos los módulos. Los módulos son una colección de paquetes de Golang que en conjunto forman una aplicación o librería. Entre los beneficios de los módulos de Golang se encuentran:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Especificar las dependencias y sus versiones.&lt;/li&gt;
&lt;li&gt;Facilitar la descarga de las dependencias de un proyecto y compartirlas.&lt;/li&gt;
&lt;li&gt;Gestionar las importaciones de paquetes que componen el módulo.&lt;/li&gt;
&lt;li&gt;Actualizar y sincronizar las dependencias de un proyecto.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Los módulos en Golang se definen con el archivo &lt;code&gt;go.mod&lt;/code&gt; en la raíz del proyecto y este archivo tiene la siguiente estructura:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;module&lt;/span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;nombre&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;del&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;modulo&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;go&lt;/span&gt; &amp;lt;&lt;span style="color:#c678dd"&gt;go&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;version&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#61afef;font-weight:bold"&gt;require&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;dependencia&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&amp;gt; &amp;lt;&lt;span style="color:#e06c75"&gt;version&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;dependencia&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&amp;gt; &amp;lt;&lt;span style="color:#e06c75"&gt;version&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#61afef;font-weight:bold"&gt;replace&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;dependencia&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&amp;gt; =&amp;gt; &amp;lt;&lt;span style="color:#e06c75"&gt;ruta&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;local&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;dependencia&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;&amp;gt; =&amp;gt; &amp;lt;&lt;span style="color:#e06c75"&gt;nueva&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;dependencia&lt;/span&gt;&amp;gt; &amp;lt;&lt;span style="color:#e06c75"&gt;version&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En la anterior estructura se identifican cuatro partes principales:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;El nombre del módulo:&lt;/strong&gt; Este puede tener cualquier nombre, sin embargo, es buena práctica definir un dominio en donde se alojará el módulo seguido de un path único.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Definir la versión de Go:&lt;/strong&gt; Especifica la versión de Golang que se usará en el proyecto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Las dependencias del proyecto:&lt;/strong&gt; Se especifica el nombre de la dependencia y la versión que se usará. Esta sección no es obligatoria si el módulo no tiene dependencias.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Directiva &lt;code&gt;replace&lt;/code&gt;:&lt;/strong&gt; Permite reemplazar las dependencias del módulo por otras dependencias o rutas locales, lo cual veremos en profundidad más adelante.&lt;/li&gt;
&lt;/ol&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Podemos hacer la analogía del archivo &lt;code&gt;go.mod&lt;/code&gt; con el archivo &lt;code&gt;package.json&lt;/code&gt; de Node.js o el archivo &lt;code&gt;requirements.txt&lt;/code&gt; de Python.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Junto con el archivo &lt;code&gt;go.mod&lt;/code&gt; encontramos el archivo &lt;code&gt;go.sum&lt;/code&gt;, el cual es un archivo autogenerado que no debes modificar manualmente. Este archivo contiene el listado de todos los paquetes de dependencias del módulo y sus respectivas versiones, sirviendo como referencia para verificar que las dependencias del módulo no hayan sido modificadas.&lt;/p&gt;
&lt;h2 id="cómo-interactuar-con-los-módulos-de-golang"&gt;¿Cómo interactuar con los módulos de Golang?&lt;/h2&gt;
&lt;p&gt;Aunque podemos crear nuestros módulos manualmente creando el archivo &lt;code&gt;go.mod&lt;/code&gt; y definiendo las dependencias, Golang nos provee de una serie de comandos para interactuar con los módulos. Los más importantes son:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;go mod init &amp;lt;module-name&amp;gt;&lt;/code&gt; ➔ Inicializa un módulo de Golang en el directorio actual, recibe como parámetro el nombre del módulo y creará el archivo &lt;code&gt;go.mod&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go mod get &amp;lt;package-name&amp;gt;&lt;/code&gt; ➔ Descarga un paquete de dependencia del módulo y lo registra dentro del archivo &lt;code&gt;go.mod&lt;/code&gt;. Adicionalmente, puedes actualizar un paquete del módulo usando la bandera &lt;code&gt;-u&lt;/code&gt;, con el comando &lt;code&gt;go get -u &amp;lt;package-name&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go mod tidy&lt;/code&gt; ➔ Sincroniza el estado actual del módulo en el archivo &lt;code&gt;go.mod&lt;/code&gt;, eliminando las dependencias que no se estén usando y agregando las que faltan pero que sí se están usando.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go mod verify&lt;/code&gt; ➔ Verifica que las dependencias del módulo descargadas no hayan tenido modificaciones y estén sincronizadas con el archivo &lt;code&gt;go.sum&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Un comando que no forma parte de &lt;code&gt;go mod&lt;/code&gt; pero que es muy útil es &lt;code&gt;go list -m all&lt;/code&gt;, el cual lista todas las dependencias del módulo y sus respectivas versiones.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-es-go-workspace"&gt;¿Qué es Go Workspace?&lt;/h2&gt;
&lt;p&gt;Hasta este punto, hemos visto qué son y cómo se usan los módulos, pero hay una característica adicional asociada al contexto de los módulos. Cuando trabajamos en un módulo dentro de nuestro editor de código, Go tiene como contexto el directorio del módulo. El problema surge cuando queremos trabajar con varios módulos al mismo tiempo, ya que Go no sabría identificar en qué módulo estamos trabajando.&lt;/p&gt;
&lt;p&gt;Este era un problema común en el desarrollo, ya que muchas veces se tenían módulos que dependían de otros módulos también desarrollados por el mismo equipo. En estos casos, si necesitabas probar cambios de un módulo en otro, tenías que actualizar la dependencia en cuestión y posteriormente actualizarla en el módulo que la usará, haciendo tedioso el proceso de desarrollo.&lt;/p&gt;
&lt;p&gt;Normalmente, para solucionar esto, el desarrollador tenía que configurar manualmente las dependencias que estaba probando para que estas apuntaran a otro módulo o una ruta dentro de su máquina local. Esto se hace con la directiva &lt;code&gt;replace&lt;/code&gt; que &lt;a href="#qu%c3%a9-son-los-m%c3%b3dulos-de-golang"



 


&gt;mencionamos antes&lt;/a&gt;. Este proceso se hacía manualmente y debías estar pendiente de actualizar y revertir los cambios antes de actualizar el paquete en el repositorio.&lt;/p&gt;
&lt;p&gt;Dado todos estos inconvenientes, se agregó &lt;code&gt;go.work&lt;/code&gt; al ecosistema. La principal funcionalidad de los Go Workspaces es facilitar la gestión de los módulos en un mismo editor o contexto. Entre las ventajas de usar Go Work encontramos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Permite trabajar con múltiples módulos en un mismo editor.&lt;/li&gt;
&lt;li&gt;Puedes unificar el desarrollo de aplicaciones de Go que se componen de múltiples módulos en un mismo repositorio o ruta de trabajo.&lt;/li&gt;
&lt;li&gt;Mejora el flujo de desarrollo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Su uso es muy similar a lo que ya vimos para &lt;code&gt;go.mod&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;go.work&lt;/code&gt; se agregó en la versión 1.18 de Go, por lo que si estás usando una versión anterior a esta, no podrás usar &lt;code&gt;go.work&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="cómo-usar-gowork"&gt;¿Cómo usar go.work?&lt;/h2&gt;
&lt;p&gt;Lo primero que debemos hacer es crear el archivo &lt;code&gt;go.work&lt;/code&gt; en la raíz del proyecto. Este archivo tiene la siguiente estructura:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;go&lt;/span&gt; &amp;lt;&lt;span style="color:#c678dd"&gt;go&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;version&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#61afef;font-weight:bold"&gt;use&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#56b6c2"&gt;/&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;module&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;path&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dentro de la estructura encontramos dos partes principales:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;La versión de Go:&lt;/strong&gt; Especifica la versión de Golang que se usará en el proyecto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Directiva &lt;code&gt;use&lt;/code&gt;:&lt;/strong&gt; Especifica la ruta del módulo que se usará en el proyecto.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Aunque podemos crear el archivo manualmente, lo recomendable es hacerlo a través de los comandos de Go que están definidos para los Workspaces. Al igual que los módulos de Go, Go Work tiene una serie de comandos que nos permiten interactuar con los Workspaces. Los más importantes son:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;go work init&lt;/code&gt; ➔ Inicializa un Workspace de Golang en el directorio actual, creando el archivo &lt;code&gt;go.work&lt;/code&gt; en la raíz del directorio.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go work use &amp;lt;module-path&amp;gt;&lt;/code&gt; ➔ Agrega un módulo al Workspace. Este módulo debe estar ya creado dentro del folder &lt;code&gt;&amp;lt;module-path&amp;gt;&lt;/code&gt;, lo que significa que debe de tener definido el archivo &lt;code&gt;go.mod&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go work sync&lt;/code&gt; ➔ Sincroniza los módulos del Workspace. Este comando descarga las dependencias de los módulos que están definidos dentro del Workspace.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Si estás trabajando con un Workspace y un módulo que no está definido en el Workspace, Go no sabrá en qué módulo estás trabajando y te lanzará un error.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Con estos comandos, podrás interactuar con los módulos de Golang y el mismo Workspace será el encargado de resolver las dependencias sin necesidad de realizar configuraciones adicionales. Para explicar mejor qué significa esto, supongamos que tenemos el siguiente sistema de archivos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proyecto/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── go.work
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── modulo1/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── modulo2/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podríamos ejecutar comandos Go directamente dentro del módulo de la siguiente manera:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go &lt;span style="color:#e5c07b"&gt;test&lt;/span&gt; ./modulo1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go build ./modulo2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Todo desde la raíz del Workspace. Si no usáramos Workspace, tendríamos que abrir cada módulo en un nuevo editor o realizar las configuraciones pertinentes para que Go entienda qué módulo estamos trabajando.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;p&gt;Este artículo se basa en mi experiencia como desarrollador y en la documentación que podemos encontrar en:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.dev/blog/get-familiar-with-workspaces"




 target="_blank"
 


&gt;Get familiar with workspaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.dev/doc/tutorial/workspaces"




 target="_blank"
 


&gt;Tutorial: Getting started with multi-module workspaces&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Colecciones en Python: namedtuple()</title><link>https://blog.dacadev.com/python/colecciones/namedtuples/</link><pubDate>Tue, 14 May 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/colecciones/namedtuples/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Descubre cómo namedtuple() del módulo collections en Python optimiza el manejo de estructuras de datos con ejemplos prácticos. Aprende a mejorar la legibilidad y eficiencia de tu código con namedtuple().</description><media:content url="https://blog.dacadev.com/images/programming/python/collections/namedtuples/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-namedtuple"&gt;¿Qué es &lt;code&gt;namedtuple()&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplos-de-uso"&gt;Ejemplos de uso&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#crear-una-namedtuple"&gt;Crear una &lt;code&gt;namedtuple&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#crear-una-namedtuple-con-valores-por-defecto"&gt;Crear una &lt;code&gt;namedtuple&lt;/code&gt; con valores por defecto&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#controlar-el-renombramiento-de-los-campos"&gt;Controlar el renombramiento de los campos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#las-namedtuples-son-clases"&gt;Las &lt;code&gt;namedtuples&lt;/code&gt; son Clases&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#por-qué-usar-namedtuples"&gt;¿Por qué usar &lt;code&gt;namedtuples&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo, conocerás la función &lt;code&gt;namedtuple&lt;/code&gt; del módulo &lt;code&gt;collections&lt;/code&gt; de la biblioteca estándar de &lt;strong&gt;Python&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-es-namedtuple"&gt;¿Qué es &lt;code&gt;namedtuple()&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;namedtuple()&lt;/code&gt; es una función que retorna una nueva clase, la cual permite acceder a los valores de una tupla tanto por índice como a través de un nombre definido al crear la tupla.&lt;/p&gt;
&lt;p&gt;Primero, examinaremos la firma de la función para entender cómo funciona y, posteriormente, analizaremos por qué y cuándo es beneficioso usarla.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;namedtuple&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;typename&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;field_names&lt;/span&gt;, &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;rename&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;defaults&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;module&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Esta firma revela cinco argumentos importantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;typename&lt;/code&gt;: el nombre que se asignará a la nueva clase creada.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;field_names&lt;/code&gt;: ya sea un string o un iterable de strings que representan los nombres de los campos de la tupla. El orden de estos strings determina cómo se accederán los valores.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rename&lt;/code&gt;: un valor booleano que, si se activa, permite que la función reemplace nombres duplicados o conflictivos automáticamente.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defaults&lt;/code&gt;: permite definir valores predeterminados para los campos de la tupla, asignando valores desde el final hacia el inicio de la lista de campos.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module&lt;/code&gt;: un string que asocia la nueva tupla a un módulo específico.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los argumentos definidos después de &lt;code&gt;*&lt;/code&gt; son argumentos que deben pasarse como &lt;code&gt;keyword arguments&lt;/code&gt; (es decir, como &lt;code&gt;nombre=valor&lt;/code&gt;), no de manera posicional.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="ejemplos-de-uso"&gt;Ejemplos de uso&lt;/h2&gt;
&lt;h3 id="crear-una-namedtuple"&gt;Crear una &lt;code&gt;namedtuple&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Primero, veamos cómo crear una nueva tupla sencilla:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Coordinates&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Coordinates&amp;#34;&lt;/span&gt;, [&lt;span style="color:#98c379"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;z&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Coordinates&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;x:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;y:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;y&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;z:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;z&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;x:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;], &lt;span style="color:#98c379"&gt;&amp;#39;y:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;], &lt;span style="color:#98c379"&gt;&amp;#39;z:&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El resultado de este código será:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ python main.py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Coordinates&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;1, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;2, &lt;span style="color:#e06c75"&gt;z&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;3&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; y: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt; z: &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; y: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt; z: &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Como observamos, creamos una nueva clase llamada &lt;code&gt;Coordinates&lt;/code&gt; con campos &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, y &lt;code&gt;z&lt;/code&gt;. Luego instanciamos &lt;code&gt;point_1&lt;/code&gt; y accedimos a sus valores tanto por nombre como por índice.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Al declarar &lt;code&gt;point_1&lt;/code&gt;, los valores se asignan en el mismo orden en que se especifican en la tupla: primero &lt;code&gt;x&lt;/code&gt;, después &lt;code&gt;y&lt;/code&gt;, y finalmente &lt;code&gt;z&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="crear-una-namedtuple-con-valores-por-defecto"&gt;Crear una &lt;code&gt;namedtuple&lt;/code&gt; con valores por defecto&lt;/h3&gt;
&lt;p&gt;Definiendo valores por defecto, que deben ser iterables, podemos especificar los valores que se asignarán a los campos si no se proporcionan al crear la instancia:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;UserData&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;UserData&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#98c379"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;age&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;country&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;defaults&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;example@mail.com&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;CO&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;david&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserData&lt;/span&gt;( &lt;span style="color:#98c379"&gt;&amp;#34;David&amp;#34;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;28&lt;/span&gt;, )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;juan&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserData&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Juan&amp;#34;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;24&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;juan@mail.com&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;david&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;juan&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El resultado de este código será:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UserData&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;28, &lt;span style="color:#e06c75"&gt;email&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;example@mail.com&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;country&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;CO&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UserData&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Juan&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;24, &lt;span style="color:#e06c75"&gt;email&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;juan@mail.com&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;country&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;CO&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Los valores por defecto se asignan de derecha a izquierda a los campos que no tienen valores asignados al crear la instancia.&lt;/p&gt;
&lt;p&gt;Pero debemos de tener en cuenta que si no pasamos todos los argumentos que no están definidos por defecto, la función lanzará un error.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;unknown&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserData&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;unknown&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Traceback &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;most recent call last&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File &lt;span style="color:#98c379"&gt;&amp;#34;/home/dacacode/dacadev/personal-blog/tempCodeRunnerFile.python&amp;#34;&lt;/span&gt;, line 9, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;unknown&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; UserData&lt;span style="color:#56b6c2"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TypeError: UserData.__new__&lt;span style="color:#56b6c2"&gt;()&lt;/span&gt; missing &lt;span style="color:#d19a66"&gt;2&lt;/span&gt; required positional arguments: &lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt; and &lt;span style="color:#98c379"&gt;&amp;#39;age&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="controlar-el-renombramiento-de-los-campos"&gt;Controlar el renombramiento de los campos&lt;/h3&gt;
&lt;p&gt;Activando el argumento &lt;code&gt;rename&lt;/code&gt; como &lt;code&gt;True&lt;/code&gt;, la función automáticamente renombra campos duplicados o que sean palabras reservadas del lenguaje. Primero vamos a crear una tupla normal con nombres de campos que pueden entrar en conflicto.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;dynamic_fields&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;def&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;arg&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;EspecialInfo&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;EspecialInfo&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;dynamic_fields&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;EspecialInfo&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Al ejecutar el código vas a obtener un error como el siguiente:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Traceback &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;most recent call last&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File &lt;span style="color:#98c379"&gt;&amp;#34;/home/dacacode/dacadev/personal-blog/tempCodeRunnerFile.python&amp;#34;&lt;/span&gt;, line 4, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;EspecialInfo&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; namedtuple&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;EspecialInfo&amp;#34;&lt;/span&gt;, dynamic_fields&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; File &lt;span style="color:#98c379"&gt;&amp;#34;/home/dacacode/.pyenv/versions/3.11.5/lib/python3.11/collections/__init__.py&amp;#34;&lt;/span&gt;, line 398, in namedtuple
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; raise ValueError&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Type names and field names cannot be a &amp;#39;&lt;/span&gt;..&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ValueError: Type names and field names cannot be a keyword: &lt;span style="color:#98c379"&gt;&amp;#39;def&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pero si habilitamos la opcion de &lt;code&gt;rename&lt;/code&gt; el código funcionará, ya que la función se encarga de procesar esos casos.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;dynamic_fields&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;def&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;arg&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;EspecialInfoV2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;EspecialInfoV2&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;dynamic_fields&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;rename&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;EspecialInfoV2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;data&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;EspecialInfoV2&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;print&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ahora si obtendremos un resultado positivo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;class &lt;span style="color:#98c379"&gt;&amp;#39;__main__.EspecialInfoV2&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;EspecialInfoV2&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;_1&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;print&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;arg&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;_3&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En donde podemos ver que los atributos que son &lt;code&gt;keywords&lt;/code&gt; y &lt;code&gt;duplicados&lt;/code&gt; han sido renombrados por valores posicionales, en este caso &lt;code&gt;_1&lt;/code&gt; y &lt;code&gt;_3&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="las-namedtuples-son-clases"&gt;Las &lt;code&gt;namedtuples&lt;/code&gt; son Clases&lt;/h2&gt;
&lt;p&gt;Por último, pero no menos importante, recuerda que el resultado de la función &lt;code&gt;namedtuple&lt;/code&gt; es una clase que hereda de &lt;code&gt;tuple&lt;/code&gt;, lo que significa que podemos usarla como cualquier otra clase. Por ejemplo, podemos usar la nueva clase como padre de otra para extender su funcionalidad:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Coordinates&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Coordinates&amp;#34;&lt;/span&gt;, [&lt;span style="color:#98c379"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;z&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Point&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Coordinates&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__add__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Point&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;y&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;y&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;z&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;z&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Point&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;point_2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Point&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;4&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;5&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;point_2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;point_1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;point_2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El resultado de este código será:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Point&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;1, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;2, &lt;span style="color:#e06c75"&gt;z&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;3&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Point&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;4, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;5, &lt;span style="color:#e06c75"&gt;z&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;6&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Point&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;5, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;7, &lt;span style="color:#e06c75"&gt;z&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;9&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="por-qué-usar-namedtuples"&gt;¿Por qué usar &lt;code&gt;namedtuples&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Una de las principales razones para usar las &lt;code&gt;namedtuple&lt;/code&gt; es la mejora de la legibilidad del código, ya que al momento los atributos para acceder a sus elementos es más fácil de entender que si lo hacemos por índice.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;UserInfo&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;namedtuple&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;UserInfo&amp;#39;&lt;/span&gt;, [&lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;age&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Mejora la legibilidad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserInfo&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;28&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;mail@mail.com&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;name&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# David&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;age&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;email&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# mail@mail.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Debes tener en tu mente el orden de los campos, no es lo ideal!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;userRaw&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {&lt;span style="color:#98c379"&gt;&amp;#39;David&amp;#39;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;28&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;mail@mail.com&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# David&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# mail@mail.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Otros beneficios que encontramos es en la eficiencia del código, ya que al utilizar &lt;strong&gt;tuplas&lt;/strong&gt; (o &lt;code&gt;nametuples&lt;/code&gt;) encontramos que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Las &lt;strong&gt;tuplas&lt;/strong&gt; tienen mayor rendimiento al momento de ser creadas, debido a que son objetos inmutables y su alocación en memoria es mucho ams eficiente que las clasicas lsitas o diccionarios.&lt;/li&gt;
&lt;li&gt;Son ideales para procesar información que debe mantenerse constante durante todo su tiempo de vida, ya que las tuplas son inmutables.&lt;/li&gt;
&lt;li&gt;El tiempo de acceso a los elementos de la tupla es más rápido que las listas o los diccionarios.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Esto no significa que las &lt;strong&gt;tuplas&lt;/strong&gt; sean mejores que otras estructuras de datos, esto depende de cada caso en particular y debes analizarlo antes de tomar una decisión.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;





 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Para más información sobre &lt;code&gt;namedtuple&lt;/code&gt;, visita la documentación oficial en este &lt;a href="https://docs.python.org/3/library/collections.html#collections.namedtuple"




 target="_blank"
 


&gt;&lt;strong&gt;enlace&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>RP Pico: Interrupciones de GPIO</title><link>https://blog.dacadev.com/micropython/raspberry-pico/manejo-de-interrupciones/</link><pubDate>Sun, 28 Apr 2024 21:18:46 +0000</pubDate><guid>https://blog.dacadev.com/micropython/raspberry-pico/manejo-de-interrupciones/</guid><dc:creator>Dacadev</dc:creator><category>micropython</category><description>Guía completa para configurar interrupciones GPIO en la Raspberry Pi Pico con MicroPython. Aprende sobre NVIC, tipos de triggers, flancos y ejemplos prácticos.</description><media:content url="https://blog.dacadev.com/images/micropython/rp-interrupts-gpio/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-son-las-interrupciones"&gt;¿Qué son las interrupciones?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#manejo-de-interrupciones-en-el-rp2040"&gt;Manejo de interrupciones en el RP2040&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#interrupciones-con-micropython"&gt;Interrupciones con Micropython&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#tipo-de-activadores-de-interrupciones"&gt;Tipo de activadores de interrupciones&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo aprenderás a manejar las interrupciones GPIO de la &lt;strong&gt;Raspberry Pi Pico&lt;/strong&gt; usando &lt;strong&gt;MicroPython&lt;/strong&gt;. Al final entenderás cómo configurarlas y qué tener en cuenta al diseñar el comportamiento de las interrupciones.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-son-las-interrupciones"&gt;¿Qué son las interrupciones?&lt;/h2&gt;
&lt;p&gt;Las interrupciones son acciones, normalmente una serie de tareas que se ejecutan cuando cierta condición o evento se genera durante la ejecución del programa. Haciendo que el programa se detenga en ese punto y proceda a ejecutar las acciones que se han definido para ese evento.&lt;/p&gt;
&lt;h2 id="manejo-de-interrupciones-en-el-rp2040"&gt;Manejo de interrupciones en el RP2040&lt;/h2&gt;
&lt;p&gt;Antes de configurar el código para nuestra &lt;strong&gt;RP2040&lt;/strong&gt;, es importante entender cómo maneja las interrupciones. Cada núcleo está equipado con un controlador de interrupciones propio, conocido como &lt;em&gt;Controlador de Interrupciones Vectorizadas Anidadas&lt;/em&gt; (o &lt;strong&gt;NVIC&lt;/strong&gt; por sus siglas en inglés, &lt;em&gt;Nested Vectored Interrupt Controller&lt;/em&gt;). Cada NVIC puede gestionar 32 tipos de interrupciones. Esto proporciona al &lt;strong&gt;RP2040&lt;/strong&gt; flexibilidad para manejar múltiples interrupciones de manera eficiente, permitiendo que cada núcleo responda de forma independiente a los eventos de interrupción específicos. En relación con los GPIO, cada controlador de interrupciones gestiona una única interrupción de GPIO por banco, y no una interrupción por cada pin, lo que significa que las interrupciones por pines dentro de un mismo banco son compartidas entre los pines del mismo.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Para más información de como se manejan las interrupciones en el &lt;strong&gt;RP2040&lt;/strong&gt;, puedes revisar la &lt;strong&gt;sección 2.3.2&lt;/strong&gt; del &lt;a href="https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf"




 target="_blank"
 


&gt;datasheet&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="interrupciones-con-micropython"&gt;Interrupciones con Micropython&lt;/h2&gt;




 
 






&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info &lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;A partir de este punto es necesario que el usuario tenga entendimiento de como operan la clase &lt;code&gt;Pin&lt;/code&gt; en Micropython, si ese no es el caso en el &lt;a href="#interrupciones-con-micropython"



 


&gt;&lt;strong&gt;siguiente artículo&lt;/strong&gt;&lt;/a&gt; te explico más del tema.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Para configurar las interrupciones en Micropython debemos de tener una instancia de la clase &lt;code&gt;Pin&lt;/code&gt; que encontramos en la librería &lt;code&gt;machine&lt;/code&gt;. Una vez tengas la instancia de &lt;code&gt;Pin&lt;/code&gt; el siguiente paso es asociar una interrupción al mismo, para ello haremos uso del método &lt;a href="https://docs.micropython.org/en/latest/library/machine.Pin.html#machine.Pin.irq"




 target="_blank"
 


&gt;&lt;code&gt;irq&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Este método tiene las siguientes configuraciones:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;parámetro&lt;/th&gt;
 &lt;th&gt;valor por defecto&lt;/th&gt;
 &lt;th&gt;descripción&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;handler&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;None&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Es la función que se ejecutará cuando se dispare la interrupción, esta función secibe como parámetro una instancia del &lt;code&gt;Pin&lt;/code&gt; que lo activo, si el valor es &lt;code&gt;None&lt;/code&gt; la interrupción esta desactivada&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;trigger&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;IRQ_FALLING | Pin.IRQ_RISING&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Es el comportamiento que se tendrá encuenta para activar la interrupción, mirá el &lt;a href="#tipo-de-activadores-de-interrupciones"



 


&gt;gráfico&lt;/a&gt; mas adelante, es posible mezclar mas de un tipo de activador&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;priority&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Es el nivel de prioridad que le asignarás a la interrupción, entre mayor el numero, mayor prioridad&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;wake&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;None&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Te permite controlar si la interrupción tiene la capacidad de &amp;ldquo;despertar&amp;rdquo; al procesador si esta en estado de reposo/suspención&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;hard&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;False&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Este parámetro permite definir si la interrupción será manejada por hardware o no, esto permite disminuir el delay entre la activación y la ejecución de la función de la interrupción, sin embargo tiene implicación de performance que debe considerar el desarrollador y no Micropython&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Veamos un ejemplo de como se crean interrupción con Micropython:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;machine&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;utime&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# setup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;led&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;25&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;OUT&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;btn&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;IN&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Función para manejar la interrupción&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# recibe solo un parámetro de tipo Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;interrupt_callback&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;pin&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;pin&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;led&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;toggle&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;btn&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;irq&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;handler&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;interrupt_callback&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;trigger&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;IRQ_FALLING&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="tipo-de-activadores-de-interrupciones"&gt;Tipo de activadores de interrupciones&lt;/h3&gt;
&lt;p&gt;Micropython define los siguientes activadores de interrupciones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_FALLING&lt;/code&gt; interrupción en flanco de bajada (&lt;strong&gt;falling edge&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_RISING&lt;/code&gt; interrupción en flanco de subida (&lt;strong&gt;rising edge&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_LOW_LEVEL&lt;/code&gt; interrupción en nivel bajo (&lt;strong&gt;low level&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_HIGH_LEVEL&lt;/code&gt; interrupción en nivel alto (&lt;strong&gt;high level&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recuerda que una señal digital oscila entre 1 y 0, lo cual podemos ver en el tiempo como una señal cuadrada, y en base a ella es que se tienen definidas los activadores de interrupciones, como se muestra en el siguiente gráfico.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/micropython/rp-interrupts-gpio/trigger-types_hu_2fa10276e580adee.webp"
 alt="Imagen guia del contenido de la página"style="width:400px"/&gt;
 &lt;/div&gt;
 
 
 

</content:encoded></item><item><title>Despliegue su sitio en GitHub Pages con HUGO y dominio personalizado</title><link>https://blog.dacadev.com/programacion/despliega-tu-sitio-de-hugo-en-github-pages/</link><pubDate>Mon, 18 Dec 2023 20:56:15 +0000</pubDate><guid>https://blog.dacadev.com/programacion/despliega-tu-sitio-de-hugo-en-github-pages/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Explora esta guía detallada para desplegar sitios web en GitHub Pages usando HUGO. Aprende a configurar tu sitio, automatizar con GitHub Actions y personalizar tu dominio. Ideal para desarrolladores y creadores de contenido que buscan una solución rápida y efectiva.</description><media:content url="https://blog.dacadev.com/images/programming/tutorials/deploy-hugo-site-in-github-pages/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#despliegue-paso-a-paso-del-sitio-en-github-pages"&gt;Despliegue paso a paso del sitio en &lt;strong&gt;GitHub&lt;/strong&gt; Pages&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#configura-un-dominio-personalizado-en-github-pages"&gt;Configura un dominio personalizado en &lt;strong&gt;GitHub Pages&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este tutorial aprenderás a desplegar un sitio web creado con &lt;strong&gt;Hugo&lt;/strong&gt; en &lt;strong&gt;GitHub Pages&lt;/strong&gt; en menos de 10 minutos, automatizar el despliegue con &lt;strong&gt;GitHub Actions&lt;/strong&gt; y configurar un dominio personalizado.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;HUGO&lt;/strong&gt; es un generador de sitios estáticos creado en Go, que cuenta con un rendimiento excelente y varias funcionalidades que permiten crear sitios web de manera amigable tanto para desarrolladores como para creadores de contenido.&lt;/p&gt;
&lt;p&gt;Para saber más de la herramienta, puedes remitirte a la documentación en el siguiente &lt;a href="https://gohugo.io/"




 target="_blank"
 


&gt;link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Para desplegar tu sitio web creado con &lt;strong&gt;HUGO&lt;/strong&gt;, dispones de muchas herramientas, tanto pagas como gratuitas, que te pueden ayudar en este proceso. En este post, vamos a ver cómo podemos desplegar rápidamente nuestro sitio en GitHub Pages en menos de 10 minutos y actualizar el dominio a uno personalizado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GitHub Pages&lt;/strong&gt; es un servicio que ofrece &lt;strong&gt;GitHub&lt;/strong&gt; para los repositorios públicos o para aquellos usuarios que cuentan con una suscripción pro, sean usuarios personales o empresariales.&lt;/p&gt;
&lt;h2 id="despliegue-paso-a-paso-del-sitio-en-github-pages"&gt;Despliegue paso a paso del sitio en &lt;strong&gt;GitHub&lt;/strong&gt; Pages&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Debes tener un proyecto de HUGO funcional y alojarlo en un repositorio público en &lt;strong&gt;GitHub&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Si quieres que el repositorio sea privado y aún así desplegar tu sitio, es importante contar con la cuenta Pro.&lt;/p&gt;
&lt;p&gt;En la imagen de referencia, estoy usando la página especial de &lt;strong&gt;GitHub Pages&lt;/strong&gt; que coincide con mi nombre de usuario, &lt;a href="https://github.com/dacadev-official"




 target="_blank"
 


&gt;dacadev-official&lt;/a&gt;. Esto significa que cuando despliegue mi sitio, lo harán en la raíz del dominio de mi cuenta, que sería &lt;code&gt;https://dacadev-official.github.io&lt;/code&gt;. Si el nombre fuera diferente, la URL sería &lt;code&gt;https://dacadev-official.github.io/&amp;lt;my-repo-name&amp;gt;&lt;/code&gt;. Es importante tener esto en cuenta ya que si en &lt;strong&gt;HUGO&lt;/strong&gt; estamos usando &lt;code&gt;Permalinks&lt;/code&gt; o &lt;code&gt;relURL&lt;/code&gt; sin tener configurado debidamente nuestro &lt;code&gt;baseurl&lt;/code&gt;, podría generar problemas en los enlaces.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Dentro de nuestro repositorio, nos dirigiremos a la sección de &lt;em&gt;settings &amp;gt; pages&lt;/em&gt; y activaremos la opción de build and deploy con &lt;strong&gt;GitHub Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;El siguiente paso consiste en activar las &lt;strong&gt;GitHub Actions&lt;/strong&gt;. Para ello, debemos crear un archivo dentro del folder &lt;code&gt;.github/workflows&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Las &lt;strong&gt;GitHub Actions&lt;/strong&gt; son una herramienta de automatización integrada en GitHub, que permite ejecutar flujos de trabajo basados en eventos dentro de un repositorio.&lt;/p&gt;
&lt;p&gt;Crearemos el archivo &lt;code&gt;hugo.yaml&lt;/code&gt; dentro del folder mencionado. Puede ser cualquier nombre, pero lo importante es que sea un nombre relacionado o descriptivo de lo que hará. Dentro de este archivo, colocaremos el siguiente contenido.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# Nombre de la acción&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Deploy Hugo site to Pages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Se activara cuando se haga un push sobre la rama main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Permisos para que pueda leer el contenido del repo y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# pueda escribir sobre la funcionalidad de GitHub Pages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;contents&lt;/span&gt;: read
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;pages&lt;/span&gt;: write
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;id-token&lt;/span&gt;: write
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Estara asociado al grupo relacionados con pages y no cancelará&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# otros procesos que esten en ejecución&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;concurrency&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;group&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;pages&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;cancel-in-progress&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Define bash como el encargado de ejecutar los trabajos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;defaults&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;run&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;shell&lt;/span&gt;: bash
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# En este apartado define el entorno usado para el workflow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#7f848e"&gt;# 1 TRABAJO DE CONSTRUCCIÓN DEL SITIO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# Entorno&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#7f848e"&gt;# Esta variable permite cambiar facilmente la version de HUGO usada&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;HUGO_VERSION&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.121.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Install Hugo CLI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;run&lt;/span&gt;: |&lt;span style="color:#98c379"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;amp;&amp;amp; sudo dpkg -i ${{ runner.temp }}/hugo.deb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Install Dart Sass
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;run&lt;/span&gt;: sudo snap install dart-sass
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#7f848e"&gt;# Prepara el entorno para desplegar las páginas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Checkout
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;uses&lt;/span&gt;: actions/checkout@v4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;submodules&lt;/span&gt;: recursive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;fetch-depth&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Setup Pages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: pages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;uses&lt;/span&gt;: actions/configure-pages@v4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Install Node.js dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;run&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;yarn install&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#7f848e"&gt;# Configura las variables de entorno de HUGO y procede a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;				&lt;span style="color:#7f848e"&gt;# ejecutar el comando para construir el sitio.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Build with Hugo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;HUGO_ENVIRONMENT&lt;/span&gt;: production
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;HUGO_ENV&lt;/span&gt;: production
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;run&lt;/span&gt;: |&lt;span style="color:#98c379"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; hugo \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; --gc \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; --minify \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; --baseURL &amp;#34;${{ steps.pages.outputs.base_url }}/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#7f848e"&gt;# Sube el contenido generado por hugo al directorio de GitHub Pages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			- &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Upload artifact
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;uses&lt;/span&gt;: actions/upload-pages-artifact@v2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;path&lt;/span&gt;: ./public
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# 2 REDESPLIEGA EL SITIO EN GITHUB PAGES CON LOS NUEVOS CAMBIOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;deploy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: github-pages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;url&lt;/span&gt;: ${{ steps.deployment.outputs.page_url }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;runs-on&lt;/span&gt;: ubuntu-latest
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;needs&lt;/span&gt;: build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: Deploy to GitHub Pages
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;id&lt;/span&gt;: deployment
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;uses&lt;/span&gt;: actions/deploy-pages@v3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;El siguiente paso es hacer commit con el nuevo archivo agregado, con un mensaje descriptivo, y finalmente hacer push de los cambios a la rama main o la que hayas definido en el archivo .yaml de configuración.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;git commit -m &amp;ldquo;feat: implement github actions to deploy site into GitHub Pages&amp;rdquo;
git push origin main&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nos dirigiremos a la página de nuestro repositorio y veremos que &lt;strong&gt;GitHub&lt;/strong&gt; ha detectado automáticamente nuestros cambios con las acciones y las ejecutará. Verás algo similar a la siguiente imagen.
Una vez que se completen los workflows correctamente, debes dirigirte a la URL del repositorio, que sería &lt;code&gt;https://&amp;lt;username&amp;gt;.github.io/&amp;lt;repository&amp;gt;&lt;/code&gt;. Recuerda que si tu repositorio tiene el mismo nombre que tu usuario, puedes omitir el &lt;code&gt;&amp;lt;repository&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En caso de que se genere un error o algo similar debes de revisar los logs de cada paso que enontrarás en el link de details al lado de cada uno de los pasos&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="configura-un-dominio-personalizado-en-github-pages"&gt;Configura un dominio personalizado en &lt;strong&gt;GitHub Pages&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Hasta este punto, hemos configurado y desplegado exitosamente nuestro sitio en &lt;strong&gt;GitHub Pages&lt;/strong&gt;. Ahora, lo que nos falta es configurar nuestro nombre de dominio para que tenga un nombre de nuestra marca o necesidad en cuestión.&lt;/p&gt;
&lt;p&gt;En este ejemplo, hemos usado un dominio adquirido en &lt;a href="https://www.namecheap.com/"




 target="_blank"
 


&gt;Namecheap&lt;/a&gt; que tenemos listo para configurar.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lo primero que haremos es configurar nuestro dominio dentro de nuestro repositorio. Para ello, nos dirigiremos a settings &amp;gt; pages de nuevo y buscaremos la opción de Custom Domain.&lt;/li&gt;
&lt;li&gt;Dentro del input, agregamos el dominio que queremos agregar.&lt;/li&gt;
&lt;li&gt;El siguiente paso será configurar las direcciones IP a las cuales queremos que apunte nuestro dominio. Para ello, nos dirigiremos al panel de control de Namecheap e iremos a las opciones avanzadas de nuestro dominio.
Las URL listadas son las siguientes:
&lt;ul&gt;
&lt;li&gt;185.199.108.153&lt;/li&gt;
&lt;li&gt;185.199.109.153&lt;/li&gt;
&lt;li&gt;185.199.110.153&lt;/li&gt;
&lt;li&gt;185.199.111.153&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Lo que estamos configurando es lo siguiente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Registros A&lt;/strong&gt; con la dirección &lt;code&gt;@&lt;/code&gt;, que representa la raíz del dominio, apuntando a cuatro direcciones IP diferentes. Son necesarios para que tu dominio personalizado apunte a los servidores de &lt;strong&gt;GitHub Pages&lt;/strong&gt;. Esto permite que cuando alguien ingrese tu dominio en su navegador, la solicitud sea dirigida a los servidores de GitHub, donde está alojado tu proyecto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Registro CNAME&lt;/strong&gt; con el host &lt;code&gt;www&lt;/code&gt; y el valor &lt;code&gt;&amp;lt;username&amp;gt;.github.io&lt;/code&gt;., redirige las solicitudes de &lt;code&gt;www.tudominio.com&lt;/code&gt; al subdominio&lt;code&gt; &amp;lt;username&amp;gt;.github.io&lt;/code&gt; en &lt;strong&gt;GitHub&lt;/strong&gt;. Esto es útil si quieres que tanto &lt;code&gt;www.tudominio.com&lt;/code&gt; como &lt;code&gt;tudominio.com&lt;/code&gt; muestren tu proyecto en &lt;strong&gt;GitHub Pages&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ya con esto, tu sitio estaría listo para servir a través de tu dominio personalizado.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Debes esperar un tiempo para que GitHub confirme que el dominio ingresado está configurado correctamente. Normalmente esto puede tomar entre unos minutos hasta 24 horas dependiendo de la propagación DNS.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item></channel></rss>