Skip to content
edge-language-tools
Esc
navigateopen⌘Jpreview
On this page

Model-backed props

Rename a database column and watch every affected template light up.

The @types body accepts any TypeScript type expression, so templates can declare their props straight from your application’s models — the same types your controllers and ORM already use. No duplicated shapes, no drift.

Point templates at the real model

{{--
@types {
  user: import('#models/user').User
  posts: import('#models/post').Post[]
}
--}}
<h1>{{ user.fullName }}</h1>
@each(post in posts)
  <article>
    <h2>{{ post.title }}</h2>
    <time>{{ post.publishedAt.toFormat('yyyy-MM-dd') }}</time>
  </article>
@end
export class User {
  declare id: number
  declare fullName: string
  declare email: string
}

Imports resolve through your tsconfig.json, so #models/* path aliases work — this is the AdonisJS layout, but any exported type from any .ts file does the same job.

The payoff: refactors reach into templates

Rename fullName on the model:

Without types, that’s a grep and a prayer — templates fail silently at runtime, in production, on the page you didn’t test. With the model imported:

  • {{ user.fullName }} squiggles in every open template, with Did you mean ‘displayName’?
  • edge-check templates/ fails CI listing every affected file:line
  • tsc catches the controllers at the same time — one rename, every consumer flagged, including the views

Templates stop being the place where refactors go to die.

Was this page helpful?