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

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions