Fixing Astro's 'Import Declaration Conflicts' Error

I hit a weird error in Astro today that I hadn’t seen before: Import declaration conflicts with local declaration of 'Search'. It took me a minute to figure out what was going on, so I’m writing this down in case it helps someone else.

The problem was pretty simple. I had a page at src/pages/cookbooks/[cookbook]/search.astro. In Astro, any file in the src/pages directory becomes a page, and the file itself acts as a component. So, my search.astro file was implicitly creating a component named Search.

The conflict happened because I was also trying to import a different component named Search from src/components/Search.astro to use inside my page.

src/pages/cookbooks/[cookbook]/search.astro
---
// This import causes the name conflict
import Search from "../../../components/Search.astro";
---

<!-- ... -->

Astro saw two different things named Search in the same file and threw an error. One was the page component itself, and the other was the one I was importing.

Shell
src/pages/cookbooks/[cookbook]/search.astro:56:6 - error ts(2322): Type '{}' is not assignable to type 'IntrinsicAttributes & { cookbook: { id: string; body?: string; collection: "cookbooks"; data: { title: string; description: string; recipes: ReferenceDataEntry<"recipes", string>[]; sidebar: { ...; }; overview: ReferenceDataEntry<...>; }; rendered?: RenderedContent; filePath?: string; }; }'.
  Property 'cookbook' is missing in type '{}' but required in type '{ cookbook: { id: string; body?: string; collection: "cookbooks"; data: { title: string; description: string; recipes: ReferenceDataEntry<"recipes", string>[]; sidebar: { title: string; items: ({ ...; } | { ...; })[]; }; overview: ReferenceDataEntry<...>; }; rendered?: RenderedContent; filePath?: string; }; }'.

56     <Search />
        ~~~~~~
src/pages/cookbooks/[cookbook]/search.astro:5:8 - error ts(2440): Import declaration conflicts with local declaration of 'Search'.

5 import Search from "../../../components/Search.astro";

The fix is to rename the imported component using an as keyword. This is called an “aliased import”. It lets you give the imported component a new name inside the file.

So, I changed my import from this:

TypeScript
import Search from "../../../components/Search.astro";

To this:

TypeScript
import SearchComponent from "../../../components/Search.astro";

Then, I just had to update my template to use the new name:

src/pages/cookbooks/[cookbook]/search.astro
---
import SearchComponent from "../../../components/Search.astro";
---

<MinimalLayout>
    <SearchComponent />
</MinimalLayout>

By renaming the imported component to SearchComponent, the name conflict was gone. It’s a simple fix, but it’s one of those things that can be confusing if you don’t know why it’s happening.