Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

packages/cli 生成的临时 app 自带 strict + noUnusedLocals 的 tsconfig,但从来没有任何东西跑过 tsc —— 产物里有一批 TS 错(未用 import、隐式 any) #3853

Closed

Description

@yinlianghui

越界发现,记录于 #3827 实施期间(核实生成产物 import/声明对应关系时顺手跑了一次 tsc)。#3827 的面是清单声明与版本区间,这一条是生成的 TS 源码本身,故只记录。

事实(对 origin/main @ 844d17fc9 实测)

packages/cli/src/utils/app-generator.ts 两个生成器都写出这份 tsconfig.json:

strict: true,
noUnusedLocals: true,
noUnusedParameters: true,

而生成的源码过不了它。把 createTempAppWithRouting 生成到一个目录再用它自己的 tsconfig 跑 tsc -p tsconfig.json,与模块解析无关的错(即与 @object-ui/* 是否装上无关的那些)如下:

src/App.tsx(1,40):   error TS6133: 'Link' is declared but its value is never read.
src/Layout.tsx(7,3): error TS6133: 'cn' is declared but its value is never read.
src/Layout.tsx(8,3): error TS6133: 'Button' is declared but its value is never read.
src/Layout.tsx(20,3): error TS6133: 'SidebarGroupContent' is declared but its value is never read.
src/Layout.tsx(21,3): error TS6133: 'SidebarGroupLabel' is declared but its value is never read.
src/Layout.tsx(36,24): error TS7031: Binding element 'name' implicitly has an 'any' type.
src/Layout.tsx(36,30): error TS7031: Binding element 'className' implicitly has an 'any' type.
src/Layout.tsx(79,22): error TS7031: Binding element 'app' implicitly has an 'any' type.
src/Layout.tsx(79,27): error TS7031: Binding element 'children' implicitly has an 'any' type.
src/Layout.tsx(101,26): error TS7006: Parameter 'item' implicitly has an 'any' type.
src/Layout.tsx(101,32): error TS7006: Parameter 'idx' implicitly has an 'any' type.
src/Layout.tsx(104,56): error TS7006: Parameter 'child' implicitly has an 'any' type.

两类:

  1. 声明了没用的 import(TS6133):App.tsx 的 Link 从 react-router-dom 拿进来但只在 Layout.tsx 里用;Layout.tsx 从 @object-ui/components 一次拿 24 个名字,其中 cn / Button / SidebarGroupContent / SidebarGroupLabel 四个没用上。
  2. 隐式 any(TS7031/TS7006):DynamicIcon 与 AppLayout 的 props 解构、以及 menu.map / children.map 的回调参数都没标类型,在 strict 下即错。

另有 src/theme-provider.tsx 用 React.ReactNode 作类型但只 import { createContext, useContext, useEffect, useState } from "react",没有把 React 作为命名空间引入 —— 模块里引用 UMD 全局命名空间需要 allowUmdGlobalAccess,生成的 tsconfig 没开。这条我没能在同一次 tsc 里干净地隔离出来(那次运行里 @object-ui/* 的类型没解析成功,噪音盖住了),所以标注为待核,不作为已证事实。

影响:今天没有东西是红的(故打 finding)

可选方向(不预设结论)

  1. 把生成源码改到能过自己的 tsconfig(补类型标注、删掉没用的 import),并在生成产物测试里加一道真 tsc —— 最彻底,也和 packages/cli 的 createTempAppWithRouting 生成的 app import 了未声明的 lucide-react,且其工具链区间落后仓内一到三个 major #3827 刚落的"生成产物用结构性闸门钉住"同取向。
  2. 只删没用的 import(TS6133 那五条),隐式 any 另开。
  3. 反过来把生成的 tsconfig 放松到与产物一致(去掉 noUnusedLocals / 降 strict)。最省事,但这是把 declared 往 enforced 的反方向调,与仓内 contract-first 的取向相反,我不倾向。

倾向方向 1;若嫌一次性太大,方向 2 + 隐式 any 单独排队也说得通。


Generated by Claude Code

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Findings triage: held as finding (label unchanged).

    Why it stays held: declared-not-enforced debt with nothing red today — the generated tsconfig.json (noUnusedLocals live at app-generator.ts:430/:1004 on origin/main @ 993336f) is never executed by any command (dev/serve/build are vite transpile-only, noEmit: true), so the TS6133/TS70xx inventory bites only on scaffold-copy-out or once a real tsc gate exists. Observation-class per the seat's grading criteria.

    Restart conditions: ① a tsc gate over generated products is actually proposed/landed (the natural slot is the #3827 structural-gate family — that PR deliberately scoped the type face out); or ② a real scaffold-export use case appears. Direction note for that day: direction 1 (fix the generated sources + add a real tsc in generated-product tests) per the author's lean; direction 3 (loosen the tsconfig) runs against declared=enforced and should not be the default. The theme-provider.tsx UMD-namespace item is marked 待核 by the author and stays unverified — re-measure before acting on it.

    Dedup: distinct from #3852 (CSS pipeline, queued this round) and #3827 (manifest/version anchoring, in flight) — three disjoint faces of the same generator, cross-linked.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    Collaborator

    Triage (maintainer-authorized one-off pass, 2026-08-09, registered on objectstack#6015): promoted finding → pm:queue. The generated app is a first-hour surface: a scaffold that ships its own strict tsconfig and then fails that config's check the moment a user runs tsc is the follow-the-docs-and-fail shape. Deliverable: fix the generated sources to pass their own declared config, and add the missing tsc pass to whatever check covers the generator's fixtures so it stays true.


    Generated by Claude Code

  3. self-assigned this
    on Aug 10, 2026
  4. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    ContributorAuthor

    Claim: PM loop round 5 (rolling slot refill)
    Session: session_017Qqyix2QcnpUC9XeYVDzx3 · Branch: claude/issue-3853-generated-app-tsc · Worktree: objectui-issue-3853
    File surface: packages/cli/src/utils/app-generator.ts (generated-source templates) + the generated-artifact test that gains a real tsc gate. Serial constraints: disjoint from the other four in flight; #4099 (template dep ratchets) already merged, rebase-clean expected.
    Container & model: M, mode:subagent, model: opus

    Delegated ruling on the card's fork (maintainer's 2026-08-10 delegation; veto window open until merge): Direction 1 — fix the generated source to pass its own declared tsconfig (type the props/callbacks, drop the unused imports) AND add a real tsc -p gate over a generated artifact in the package's tests, same orientation as #3827's structural gates. Direction 3 (loosening the generated tsconfig) is rejected for the reason the card itself gives: it moves declared away from enforced, against the repo's contract-first discipline. The theme-provider.tsx UMD-namespace note is flagged 待核 in the card — verify it in the clean tsc run and fix it if real.


    Generated by Claude Code

  5. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    ContributorAuthor

    ACCEPT (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4113, Direction 1 of the delegated ruling.

    The premise check found the defect LARGER than filed — 17 module-resolution-independent errors, not 12, including a TS2882 that hits BOTH generators (the card had only measured the routed one) — and the fix covers the measured set, not the card's table. The 待核 UMD item got the right treatment: disproven with discriminating probes (a bogus namespace member reports TS2694; a wrong assignment reports TS2322 — so the namespace genuinely resolves in type position, no silent degradation), and no fix shipped for a non-defect. The gate spawns the workspace's real tsc over apps the generators actually write, using the generator's OWN temp mechanism (nothing invented), costs a measured 2.76s, and goes red on the pre-fix templates with the exact inventory. Honest reporting where it counts: the 5-of-6 prediction (TS6196 vs TS6133 for a type-only binding) is recorded IN the test, and the environment-dependent TS2578 behavior is named in the PR rather than smoothed.

    The rider finding is the best kind: #4111 — the same TS2882 in the objectui init scaffold (a THIRD generator), where it is LIVE because that scaffold's build script really runs tsc. Measured, not inferred; correctly not folded in. This seat is dispatching it now as the freed slot's refill.

    Flipping ready + auto-merge.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions