Skip to content

13 more vite-built packages ship extensionless typings, and their NAMED re-exports degrade to any instead of going missing #5439

Description

@os-support-ai

Found while implementing #5365, which was fenced by triage to @object-ui/components and @object-ui/layout. Not fixed there: two of the affected packages (plugin-list, plugin-view) had sibling cards in flight, and widening past the fence was explicitly out of that dispatch.

(Generics below are written with a space after < — GitHub's body sanitizer strips < followed by a letter as an HTML tag, and it ate them on the first revision of this issue.)

What was measured, 2026-08-20

Full build in a worktree off main 32ef595f4, counting relative specifiers in every emitted dist/**/*.d.ts (AST-located module specifiers, so JSDoc prose is excluded). Only packages that were built are listed; plugin-ai, plugin-gantt, plugin-map, plugin-markdown, plugin-timeline, plugin-tree were outside the closure built here and are untested, not clean.

package build extensionless relative specifiers in dist/**/*.d.ts
@object-ui/plugin-detail vite build 81
@object-ui/plugin-designer vite build 62
@object-ui/plugin-chatbot vite build 53
@object-ui/plugin-grid vite build 36
@object-ui/plugin-dashboard vite build 31
@object-ui/plugin-form vite build 31
@object-ui/plugin-kanban vite build 22
@object-ui/plugin-view vite build 19
@object-ui/plugin-list vite build 16
@object-ui/plugin-report vite build 14
@object-ui/plugin-charts vite build 9
@object-ui/plugin-calendar vite build 4
@object-ui/plugin-editor vite build 1

Every tsc-built package measured clean in the same sweep (auth, collaboration, i18n, mobile, permissions, providers, react, sdui-parser, types, core, fields — the two hits each in core and fields are JSDoc prose, not hops). The split is exactly the one #5365 named: bundler builds emit their typings from the other half of the build, where the source specifier survives verbatim.

The part that is NOT just "#5365 again"

#5365's two packages re-export mostly through export * from './ui'. A star re-export from a module the compiler cannot resolve contributes no names, so the consumer gets a loud TS2305: has no exported member.

These packages re-export mostly through named re-exports — export { useObjectChat } from './useObjectChat'. TypeScript still declares the name; it only fails to give it a type. So the consumer gets no error at all and a silent any.

Measured on @object-ui/plugin-chatbot, probe compiled twice against the same built dist:

type IsAny< T > = 0 extends 1 & T ? true : false;
const assertAny: IsAny< typeof useHitlInChat > = true;
  • moduleResolution: nodenext — compiles clean, i.e. the symbol IS any.
  • moduleResolution: bundlerTS2322: Type 'true' is not assignable to type 'false', i.e. properly typed.

That is the worse of the two failure modes: #5365 was a wall a consumer hit immediately, this one is a type hole that opens quietly the moment a consumer pins nodenext. It is what produces the 21 residual TS7006 on @object-ui/app-shell reported in #5365's PR.

Shape of the fix

Mechanical, and the mechanism already exists: #5365 landed scripts/vite-dts-explicit-extensions.ts, a shared vite-plugin-dts beforeWriteFile / afterBuild pair that resolves each emitted specifier against the source tree the output mirrors, throws on anything it cannot resolve, and re-checks the emitted set afterwards. Wiring it into each package's vite.config.ts is three lines per package, identical to the two already done.

Worth deciding as one batch rather than 13 cards, and worth deciding together with whether the repository wants the typings-level gate leg that #5365's triage deliberately deferred — without it, nothing stops the 14th package.

Refs #5365, #4538.

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopm:queue

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions