Skip to content

TypeScript

Regor has strong TypeScript support across app context, component context, and component head typing.

You can model app and component state with real TypeScript types (interfaces/classes), and keep runtime template syntax concise.

In template expressions, Regor resolves refs automatically, so you write user.name instead of user.name.value or user.name().

import { createApp, html, type IRegorContext, type Ref, ref } from 'regor'
interface TodoItem {
id: number
label: string
}
interface MyApp extends IRegorContext {
title: Ref<string>
items: Ref<TodoItem[]>
}
createApp<MyApp>(
{
title: ref('Todos'),
items: ref([{ id: 1, label: 'Ship' }]),
},
{
element: document.querySelector('#app')!,
template: html`<h1 r-text="title"></h1>
<li r-for="item in items" :key="item.id" r-text="item.label"></li>`,
},
)
import { createApp, html, ref, useScope } from 'regor'
class BoardApp {
query = ref('')
count = ref(0)
increment = () => this.count(this.count() + 1)
}
createApp(
useScope(() => new BoardApp()),
{
element: document.querySelector('#app')!,
template: html`<input r-model="query" />
<button @click="increment">+1</button>
<p>{{ query }} - {{ count }}</p>`,
},
)

Typed component props and context with ComponentHead<TProps>

Section titled “Typed component props and context with ComponentHead<TProps>”
import { ComponentHead, defineComponent, html, type Ref, ref } from 'regor'
type CardProps = {
title: Ref<string>
}
class CardContext {
title: Ref<string>
selected = ref(false)
constructor(head: ComponentHead<CardProps>) {
this.title = head.props.title
}
}
const Card = defineComponent<CardContext>(
html`<article :class="{ selected: selected }">
<h3 r-text="title"></h3>
</article>`,
{
props: ['title'],
context: (head) => new CardContext(head),
},
)
<Card :title="user.name"></Card>

Typed class components and behavior controls

Section titled “Typed class components and behavior controls”

You can type head in class constructors and use runtime behavior flags intentionally:

  1. head.autoProps to disable automatic parent-input assignment.
  2. head.entangle to choose two-way ref sync vs snapshot behavior.
  3. head.enableSwitch for parent-context slot evaluation.
  4. head.findContext(ServiceClass, occurrence?) for optional parent context lookup.
  5. head.requireContext(ServiceClass, occurrence?) for required parent context lookup.

Example:

class AppServices {
readonly apiBase = '/v1'
}
class ChildContext {
apiBase: string
constructor(head: ComponentHead<object>) {
const services = head.requireContext(AppServices)
this.apiBase = services.apiBase
}
}
  1. Components
  2. defineComponent API
  3. createApp API
  4. contextRegistry API