Skip to content

finding(types): ComponentRendererProps is the second dual declaration in the same two files as SchemaNode — core's is non-generic, types' is generic #4594

Description

@yinlianghui

Found while measuring #4580 (the SchemaNode reconciliation, PR #4593). Filed rather than fixed — #4580's scope is SchemaNode, and this is a second, independent pair sitting in the same two files.

The pair

packages/core/src/types/index.ts:18

export interface ComponentRendererProps {
  schema: SchemaNode;
  [key: string]: any;
}

packages/types/src/base.ts:190

export interface ComponentRendererProps< TSchema extends BaseSchema = BaseSchema > {
  schema: TSchema;
  [key: string]: any;
}

Same name, both exported from their package entry (core/src/index.ts:9 re-exports it alongside SchemaNode), from two packages the same consumers import together — the identical shape #4580 describes for SchemaNode, and it sits two lines below it in one file and seven lines below it in the other. They are not the same type: one is generic and constrains schema to the object form (TSchema extends BaseSchema), the other is non-generic and types schema as SchemaNode.

Why it is observation-class rather than a defect today

Nothing imports it. A grep across packages and apps for ComponentRendererProps finds only the two declarations, core's entry re-export, and the built .d.ts of each — zero source consumers on either side. So it has no live collision to cause, which is exactly why #4548's canary never measured one for this name while measuring 19 for SchemaNode.

That also makes it cheap to get wrong later: the day someone does import it, which declaration they get depends on which package they reached for, and the two disagree about whether a primitive node is admissible.

Interaction with #4580

Worth noting for whoever takes #4580: core's ComponentRendererProps.schema is typed SchemaNode, so if core's SchemaNode becomes a re-export of types' union, this interface's schema silently widens from "object with a required type" to "object or string | number | boolean | null | undefined" as a side effect. Harmless while it has no consumers, but it is a published surface changing without a card naming it — worth folding into the same decision rather than discovering afterwards.

Refs #4580, #4548, PR #4593.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions