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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions