Saltar al contenido
Meeko
Escribe para buscar en las guías y en la referencia de la API. Ábrela desde cualquier página con / o Ctrl K; muévete con las flechas y entra con Intro.
Empezar

Contenidos

En esta página

{expresión}

Inserta en la plantilla el valor de una expresión TypeScript como texto escapado, que se actualiza cuando cambian las señales que lee.

sintaxis Desde 1.0.0 Código fuente

{expresión} escribe en el contenido de un elemento el valor de una expresión TypeScript, siempre escapado: <, >, & y las comillas llegan como texto, nunca como HTML. La expresión ve todo lo que declara el nivel superior del <script> (señales, props, funciones, imports) y los datos que exporta el <script server> de una página.

Cada interpolación es un enlace reactivo propio: cuando cambia una señal que lee, Meeko actualiza sólo ese nodo de texto, sin volver a renderizar el componente.

Uso#

meeko
<!-- app/components/Inbox.meeko -->
<script lang="ts">
const props = defineProps<{ name: string }>();
const unread = signal(3);
</script>

<template>
  <p>{props.name} tiene {unread.value} mensajes sin leer</p>
</template>

En SSR, con name: "Ana", el párrafo dice «Ana tiene 3 mensajes sin leer»; cada valor va entre dos comentarios <!--meeko:text:N--> que la hidratación usa para encontrar su nodo. Al cambiar unread.value, sólo cambia el número.

Tipo#

meeko
<p>{user.value.name} tiene {count.value} mensajes</p>

Atributos#

Sintaxis Tipo Por defecto Descripción
{expresión} cualquier expresión TypeScript obligatorio Se evalúa en el ámbito del <script> (y de los datos de <script server>), y su resultado se escribe como texto. Sólo en el contenido de un elemento, no en los atributos.

Qué admite la expresión:

  • Cualquier expresión TypeScript: llamadas, ternarios, operadores, plantillas literales ({`${count.value} €`}), as y !.
  • Llaves propias de JavaScript: un objeto literal ({ { total: count.value }.total }), una plantilla con ${…}, cadenas con { o }, comentarios y expresiones regulares. La interpolación termina en la llave que equilibra la de apertura.
  • <, && y cadenas con etiquetas se escriben tal cual: {a<b&&c}, {ok && "<b>"}. El < de una expresión nunca abre una etiqueta.
  • Las referencias de carácter HTML (&lt;, &amp;, &#60;) se decodifican antes de evaluar, como en el valor de un atributo y en Vue: {x &amp;&amp; y} es x && y, y {'&lt;'} pinta <. Para conservar una referencia literal, escribe su & desde JavaScript: {"\x26lt;"} pinta &lt;. Los diagnósticos y los source maps señalan la posición en la fuente, después de la referencia.
  • No admite sentencias (if, const, ;): calcula el valor en el script o con un computed.

Resultado#

Un nodo de texto con String(valor), entre dos comentarios de marca: escapado en el HTML del servidor y asignado con textContent en el navegador.

Valor Texto
string, number, boolean Su conversión a texto: "Ana", 3, true.
null, undefined Su conversión a texto: null, undefined. Usa ?? "" para no pintar nada.
Un objeto o una señal [object Object]: lee .value o la propiedad que quieres.
HTML ("<b>hola</b>") El texto literal <b>hola</b>, escapado. Para insertar HTML usa la directiva html.

Ejemplos#

Valores derivados con computed#

Para un cálculo que se repite o que lee varias señales, un computed evita repetir la expresión y sólo se recalcula cuando cambian sus dependencias:

meeko
<script lang="ts">
const items = signal([{ name: "Té", price: 3.5, qty: 2 }]);
const total = computed(() => items.value.reduce((sum, item) => sum + item.price * item.qty, 0));
const money = new Intl.NumberFormat("es-ES", { style: "currency", currency: "EUR" });
</script>

<template>
  <p>Total: {money.format(total.value)}</p>
  <p>{items.value.length === 1 ? "1 artículo" : `${items.value.length} artículos`}</p>
</template>

Valores opcionales#

Con strict, TypeScript exige comprobar null antes de leer una propiedad. ?. y ?? lo resuelven en la propia expresión, y if:when estrecha el tipo de todo un bloque:

meeko
<script lang="ts">
const user = signal<{ name: string; city?: string } | null>(null);
</script>

<template>
  <p>Hola, {user.value?.name ?? "invitado"}</p>
  <p if:when="user.value">{user.value.name} vive en {user.value.city ?? "algún sitio"}</p>
</template>

Datos del servidor de una página#

Un export const del <script server> llega a la plantilla con su nombre y su tipo:

meeko
<!-- app/pages/users/[id].meeko -->
<script server lang="ts">
const { params } = usePage();
export const profile = { id: params.id, name: `Usuario ${params.id}` };
</script>

<template><h1>{profile.name}</h1></template>

Texto de usuarios, sin riesgo#

El texto siempre se escapa, así que un comentario con HTML se muestra tal cual y no se ejecuta:

meeko
<script lang="ts">
const props = defineProps<{ comment: string }>(); // "<img src=x onerror=alert(1)>"
</script>

<template><blockquote>{props.comment}</blockquote></template>

Errores comunes#

Una llave sin cerrar#

Incorrectohtml
<p>Hola {user.value.name</p>

El compilador da MEEK010: Expresión de plantilla sin cerrar, en la llave de apertura. Para escribir una llave literal en el texto, interpólala como cadena.

Correctomeeko
<p>Hola {user.value.name}</p>
<p>Las llaves se escriben {"{"} y {"}"}</p>

Una interpolación vacía#

Incorrectohtml
<p>Hola {}</p>

MEEK009: Expresión de plantilla vacía.

Correctomeeko
<p>Hola {name.value}</p>

Interpolar la señal en lugar de su valor#

{count} no es un error de tipos: la plantilla admite cualquier valor, pero pinta [object Object] y no se actualiza.

Incorrectomeeko
<button on:click="increment">{count}</button>
Correctomeeko
<button on:click="increment">{count.value}</button>

Leer una propiedad de un valor que puede ser null#

Incorrectomeeko
<p>{user.value.name}</p>

meeko check da TS18047: 'user.value' is possibly 'null'.

Correctomeeko
<p if:when="user.value">{user.value.name}</p>

Llaves en un atributo#

Las llaves sólo interpolan en el contenido. En un atributo son texto literal: title="{name}" escribe {name}.

Incorrectomeeko
<a title="{user.value.name}">Perfil</a>
Correctomeeko
<a bind:title="user.value.name">Perfil</a>

Notas#

  • SSR e hidratación. El servidor escribe el texto escapado y el navegador reclama ese nodo al hidratar: la expresión se evalúa en los dos lados con los mismos datos. Un valor distinto en cada lado (Date.now(), Math.random(), la zona horaria del navegador) produce un error de hidratación; calcúlalo en el servidor y pásalo como dato, o píntalo en onMounted.
  • Reactividad. Cada {…} se suscribe a las señales que lee y se actualiza en su sitio. Leer props.x en la plantilla sigue a la prop cuando el padre la cambia.
  • Seguridad. El escape hace segura cualquier cadena, también la de un usuario. Para HTML de confianza usa la directiva html con trustHtml.
  • Rendimiento. La expresión se vuelve a evaluar en cada cambio de sus señales: para cálculos caros o repetidos, usa un computed.
  • Tipos. meeko check y el editor comprueban cada expresión con las opciones estrictas del proyecto (strict, noUncheckedIndexedAccess) y ubican el error en la propia expresión.

Relacionado#

¿Te sirvió esta página?

Añadir un comentario

Se envía al elegir «Sí» o «No». Solo se guardan la página, tu respuesta y el comentario: ni cookies ni datos tuyos.

0 de 2000 caracteres

Editar en GitHub: docs/reference/syntax/interpolation.md