#How to use a variable in `<script>` section

8 messages · Page 1 of 1 (latest)

noble widgetBOT
#

Hi @urban owl. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

To use a variable defined in the frontmatter (the code fence section at the top of your .astro file) inside a <script> tag (which runs in the browser), you need to explicitly pass the variable from the server-side context to the client-side script. There are two main approaches in Astro:

1. Using data-* Attributes

Store the variable in a data-* attribute on an HTML element, then access it in your script using the dataset property. For example:

---
// Frontmatter: server-side
const message = "Hello from frontmatter!";
---
<!-- Pass the variable to the DOM -->
<button data-message={message}>Click me</button>
<script>
  const button = document.querySelector('button[data-message]');
  const message = button.dataset.message;
  button.addEventListener('click', () => {
    alert(message);
  });
</script>

This is the recommended and most flexible approach for passing variables from frontmatter to client-side scripts in Astro Pass frontmatter variables to scripts.

2. Using define:vars Directive

You can use the define:vars directive to pass JSON-serializable frontmatter variables directly into a <script> tag. The variable will be available as a global variable in the script:

---
// Frontmatter
const message = "Astro is awesome!";
---
<script define:vars={{ message }}>
  alert(message);
</script>

Note: Using define:vars on a <script> tag implies the is:inline directive, so your script will be inlined and not bundled define:vars.


#

Summary:

  • Use data-* attributes for maximum flexibility and when you want to attach data to specific elements.
  • Use define:vars for simple cases where you want to inject variables directly into an inline script.

Let me know if you need an example for a specific use case!

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@urban owl Kapa.ai is still learning and improving, please let me know how I did by reacting below.

urban owl
#

@noble widget I went with the second method. How can I resolve Type assertion expressions can only be used in TypeScript files. from the as HTMLSelectElement.

noble widgetBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

The error message “Type assertion expressions can only be used in TypeScript files.” occurs when you use a TypeScript type assertion (e.g., as HTMLSelectElement) inside a <script> tag in an Astro component, but the script is being processed as JavaScript, not TypeScript.

According to the Astro documentation, all scripts in <script> tags are TypeScript by default only if the script is processed by Astro (i.e., the script tag has no attributes other than src). However, when you use the define:vars directive, Astro treats the script as inline and does not process it as TypeScript—so type assertions are not allowed and will cause this error Script processing define:vars.

How to resolve:

  • Remove the type assertion and use a type-safe approach in plain JavaScript, such as a runtime check or type guard:
<script define:vars={{ message }}>
  const select = document.getElementById('my-select');
  if (select instanceof HTMLSelectElement) {
    // Now TypeScript/JS knows select is an HTMLSelectElement
    select.value = 'someValue';
  }
</script>

Summary:
You cannot use TypeScript type assertions (as HTMLSelectElement) in inline scripts with define:vars. Use runtime checks like instanceof instead.

#

If you need full TypeScript support in your script, do not use define:vars and instead use a processed <script> tag without attributes, but note that you cannot directly inject frontmatter variables this way Script processing define:vars.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: