Collection types

On this page

Collection schemas already describe each collection's frontmatter. kilim types turns them into TypeScript types, so layouts, components and plugins see page.data.date as a Date instead of unknown.

npx kilim types

It writes .kilim/types.d.ts:

// Generated by `kilim types` from the collection schemas; `kilim dev` keeps it up to date.
// Do not edit: changes are overwritten.
export {};

declare module "@kilim-dev/core" {
  interface Collections {
    blog: {
      title: string;
      date: Date;
      description?: string;
      draft?: boolean;
    };
  }
}

The starter templates already list it in tsconfig.json; in another project, add it to include:

{
  "include": ["kilim.config.ts", "layouts", "themes", ".kilim/types.d.ts"]
}

kilim types prints a note when tsconfig.json does not include the file, and kilim doctor warns when it is missing or out of date with the schemas. You rarely run it yourself: kilim dev writes it again whenever the config, the theme or other code changes.

What gets typed

  • Every collection of the config, the theme and plugins, by name.
  • The schema's output: z.coerce.date() is a Date, a field with a .default() is never undefined.
  • Frontmatter fields that plugins add, as optional members of the collections they apply to.
  • Collections without a schema, and schemas that cannot describe themselves as JSON Schema, are Record<string, unknown>.

The types come from the Standard JSON Schema of each schema, which Zod 4 provides.

In layouts

site.collections and the entries of list pages are typed per collection:

import type { LayoutProps } from "@kilim-dev/core";

export default function Home({ site }: LayoutProps) {
  return (
    <ul>
      {site.collections.blog.map((post) => (
        <li>
          <a href={post.url}>{post.data.title}</a>
          <time datetime={post.data.date.toISOString()}>{post.data.date.getFullYear()}</time>
        </li>
      ))}
    </ul>
  );
}

page can be any page, so narrow it by collection first:

if (page.collection === "blog" && page.file !== undefined) {
  page.data.date; // Date
}

CollectionPage<"blog"> is the type of one entry page, for helpers that take one. Before the first kilim types, every collection's data is Record<string, unknown>, so a site type-checks either way.