docs icon indicating copy to clipboard operation
docs copied to clipboard

How do I use one layout for .md, .mdx, and .astro files with TypeScript?

Open AleksandrHovhannisyan opened this issue 1 year ago • 0 comments

📚 Subject area/topic

Using one Layout for .md, .mdx, and .astro

📋 Page(s) affected (or suggested, for new content)

https://docs.astro.build/en/basics/layouts/#using-one-layout-for-md-mdx-and-astro

📋 Description of content that is out-of-date or incorrect

The article linked above gives the following example of an Astro layout file that accepts both JSX props and frontmatter props:

---
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
  <head></head>
  <body>
    <h1>{title}</h1>
    <slot />
  </body>
</html>

But it's unclear how this can be used together with TypeScript to get typesafety.

If I just do this, then TypeScript complains that frontmatter does not exist on Astro.props:

---
type Props = { title: string };
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
  <head></head>
  <body>
    <h1>{title}</h1>
    <slot />
  </body>
</html>
Property 'frontmatter' does not exist on type 'Props'.

So then I tried this, but that doesn't work either:

---
import type { MarkdownLayoutProps } from 'astro';

type LayoutProps = {
  title: string;
}

type Props = MarkdownLayoutProps<LayoutProps> | LayoutProps;

const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
  <head></head>
  <body>
    <h1>{title}</h1>
    <slot />
  </body>
</html>

TypeScript still complains that Astro.props.frontmatter does not exist:

Property 'frontmatter' does not exist on type 'Props'.
  Property 'frontmatter' does not exist on type 'LayoutProps'.ts(2339)

Finally, I also tried:

---
import type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{ title: string }>;
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
  <head></head>
  <body>
    <h1>{title}</h1>
    <slot />
  </body>
</html>

But then the JSX usage gives a different error:

src/pages/index.astro

---
import BaseLayout from '../layouts/BaseLayout.astro'
---

<BaseLayout title="Home page!">
    <p>test</p>
</BaseLayout>

Type '{ children: any; title: string; }' is not assignable to type 'IntrinsicAttributes & Props'.
  Property 'title' does not exist on type 'IntrinsicAttributes & Props'.

🖥️ Reproduction in StackBlitz (if reporting incorrect content or code samples)

No response

AleksandrHovhannisyan avatar Jun 26 '24 15:06 AleksandrHovhannisyan