Add orphaned-props category to the Code Health check#2022
Conversation
A prop can be declared (and even read internally) on a component while no caller anywhere in src/ ever passes it, so it's always its default/undefined value in practice. Knip doesn't catch this — it only tracks module-level exports, not JSX call sites. orphaned-props.mjs resolves each component's Props type syntactically (inline literals, named interfaces/type aliases, extends, intersections, and Pick/Omit/Partial/Required/Readonly) and cross-references it against every JSX invocation in the tree, using this repo's absolute src/-rooted imports to match usage sites back to declarations without needing a full type-checker. A component is skipped rather than guessed at when its Props type doesn't resolve cleanly, when any call site spreads attributes (which could supply any prop), or when it has zero call sites (that's dead-code territory, already covered by Knip). children is treated as satisfied by non-empty JSX content, not just an explicit attribute. Results merge into the existing Knip JSON report as a new orphanedProps category, so knip-delta.mjs's existing base-vs-head ratchet and PR-comment rendering pick it up for free.
⚪ Code HealthNo change to the dead-code surface. 60 Dead files
82 Dead symbols
14 Dead enum members
178 Unnecessary exports
8 Unused dependencies
98 Orphaned props
|
a4152a1 to
604416d
Compare
Summary
Adds a new
orphaned-propscategory to the existing Code Health PR check. A prop can be declared (and even read internally) on a component while no caller anywhere insrc/ever passes it, so it's always its default/undefined value in practice — Knip doesn't catch this since it only tracks module-level exports, not JSX call sites.orphaned-props.mjsresolves each component's Props type syntactically (inline object types, named interfaces/type aliases,extends, intersections, andPick/Omit/Partial/Required/Readonly) and cross-references it against every JSX invocation in the tree, matching usage sites back to declarations via this repo's absolutesrc/-rooted imports — no full type-checker needed.A component is skipped (never reported) rather than guessed at when:
<Foo {...rest} />) — the spread could supply any propchildrenis treated as satisfied by non-empty JSX content, not just an explicit attribute.Results merge into the existing Knip JSON report as a new
orphanedPropscategory, soknip-delta.mjs's base-vs-head ratchet and PR-comment rendering pick it up for free — no changes to the diffing/commenting logic itself beyond registering the category's label and explainer text.Heads up
Run against the current tree, this finds ~98 pre-existing orphaned props. Nothing here is blocking (the whole pipeline is informational/ratchet-forward — only new issues a PR introduces show as
+), but the first comment on this PR will show that as a sizeable "carried" baseline.Test plan
src/tree; spot-checked several findings by hand against the source (ConnectionStatusBadge.compact,CardWrapper.sx,MessageWithEmphasis.emphasisContent,OnboardGuard.children) — all genuine, no false positives found in the samplefunction Foo() {} export default Foo;were registered under two keys pointing at the same entryknip-delta.mjsrenders the new category correctly with a synthetic base/head diff