Skip to content

TS2307 on @kobalte/solidbase/default-theme/Layout: extensionless ./default-theme/* exports wildcard is unresolvable by TypeScript #157

Description

@daveycodez

Environment

  • @kobalte/solidbase 0.6.9
  • TypeScript (moduleResolution: "bundler"; same result with node16/nodenext)
  • Vite / SolidStart app

Problem

Importing a default-theme submodule that the docs/templates encourage overriding, e.g.

// src/theme/Layout.tsx (theme override re-export)
export { default } from "@kobalte/solidbase/default-theme/Layout"

fails to typecheck:

error TS2307: Cannot find module '@kobalte/solidbase/default-theme/Layout' or its corresponding type declarations.

The import works at runtime (Vite resolves it), so the break is types-only and only shows up under tsc --noEmit / in-editor.

Root cause

The exports wildcard for the default theme is extensionless:

"./default-theme/*": {
  "solid": "./dist/default-theme/*",
  "import": "./dist/default-theme/*",
  "types": "./dist/default-theme/*"
}

For the specifier @kobalte/solidbase/default-theme/Layout, wildcard substitution yields the target ./dist/default-theme/Layout — a path with no extension. Bundlers apply extension guessing and find Layout.jsx, but Node's exports resolution (which TypeScript follows exactly) treats export-map targets as literal file paths and never appends extensions. So TS looks for a file literally named dist/default-theme/Layout, finds nothing, and reports TS2307 — even though dist/default-theme/Layout.d.ts sits right next to the runtime file.

(Related but distinct from #142, which is about the .js.jsx specifiers inside the dist files; this one is about the export map itself.)

Suggested fix

The wildcard presumably stays extensionless so CSS subpaths (default-theme/index.css, Layout.module.css) keep working, so the least invasive fix is explicit entries for the JS-module subpaths users are expected to import when overriding theme components, alongside the existing wildcard (more specific patterns win):

"./default-theme/Layout": {
  "solid": "./dist/default-theme/Layout.jsx",
  "import": "./dist/default-theme/Layout.jsx",
  "types": "./dist/default-theme/Layout.d.ts"
},

(similarly for any other override points — mdx-components, context, etc.)

Alternatively, extension-full wildcards split by kind, e.g. a "./default-theme/*.css" passthrough plus "./default-theme/*" mapping to *.jsx/*.d.ts — whichever fits the file layout best.

Downstream workaround

Consumers can shim it locally with an ambient declaration, duplicating the signature from Layout.d.ts:

declare module "@kobalte/solidbase/default-theme/Layout" {
  import type { JSX, ParentProps } from "solid-js"

  const Layout: (props: ParentProps) => JSX.Element
  export default Layout
}

Happy to send a PR for the export-map change if you have a preference between the two shapes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions