Skip to content

fix: key fuse connections on pin labels (#754) - #782

Open
adityaaa-IIT-BHU wants to merge 1 commit into
tscircuit:mainfrom
adityaaa-IIT-BHU:fix/fuse-connections-pin-labels
Open

fix: key fuse connections on pin labels (#754)#782
adityaaa-IIT-BHU wants to merge 1 commit into
tscircuit:mainfrom
adityaaa-IIT-BHU:fix/fuse-connections-pin-labels

Conversation

@adityaaa-IIT-BHU

Copy link
Copy Markdown

Fixes #754

Problem

fuseProps accepted any string as a connections key, so a typo'd pin name passed validation silently:

const typo = { pin99: ".R1 > .pin1" }

fuseProps.safeParse({ name: "F1", currentRating: "1A", connections: typo })      // success ✅  ← wrong
capacitorProps.safeParse({ name: "C1", capacitance: "1uF", connections: typo })  // success ❌
resistorProps.safeParse({ name: "R1", resistance: "1k", connections: typo })     // success ❌

{ "not a pin at all": ... } and { "": ... } got through too. A fuse is a two-pin passive like a resistor or capacitor, so there's no reason for it to differ.

Cause

Two related gaps in lib/components/fuse.ts:

  1. It hand-rolled the schema as z.record(z.string(), ...) instead of using the shared createConnectionsProp helper, which keys the record on z.enum(labels) so unknown keys fail. fusePinLabels was already defined and exported in the file — it just wasn't used here.

  2. Nothing checked the schema against the interface. FuseProps declared connections?: Connections<PinLabel> while the schema produced Record<string, ...>. Fuse was the only component in lib/components/ that exported both an interface and an Inferred* type without calling expectTypesMatch, which is why the two were able to drift.

Change

  • connections: createConnectionsProp(fusePinLabels).optional()
  • Narrow the interface to Connections<FusePinLabels>, matching capacitor.ts and resistor.ts
  • Add expectTypesMatch<FuseProps, InferredFuseProps>(true) so this can't drift again

This is the idiom AGENTS.md already calls for: "Electrical connectivity should usually be connections keyed by known pin labels."

Adding the assertion to the unfixed file fails, confirming the drift was real:

error TS2345: Argument of type 'true' is not assignable to parameter of
type '"property connections has mismatched types"'.

Behaviour

connections before after
{ pin1: "net.VCC", pin2: ["net.GND"] } accepted accepted (unchanged)
{ pin99: "..." } accepted rejected
{ "not a pin at all": "..." } accepted rejected
{ "": "..." } accepted rejected
omitted undefined undefined (unchanged)

Valid fuse connections parse to exactly the same value as before, so no real circuit changes behaviour.

Generated docs were refreshed per AGENTS.md (generate-component-types, generate-manual-edits-docs, generate-readme-docs, generate-props-overview); the only diffs are the fuse sections.

Verification

  • bun test416 pass / 0 fail (was 412; +4 new tests in tests/fuse.test.ts)
  • bunx tsc --noEmit — clean (this is what exercises the new expectTypesMatch)
  • bun run format:check — clean
  • git diff --check — clean

fuseProps built its connections schema by hand with z.record(z.string(),
...), so any key passed validation — pin99, "not a pin at all", even "".
Every other two-pin passive builds it from its own pin labels via
createConnectionsProp, which keys the record on z.enum(labels).

Use createConnectionsProp(fusePinLabels), and narrow the interface to
Connections<FusePinLabels> to match capacitor and resistor.

Fuse was also the only component in lib/components/ exporting both an
interface and an Inferred* type without calling expectTypesMatch, which
is why the schema and FuseProps were able to drift apart. Add the
assertion so it can't happen again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fuseProps accepts any string as a connections key, unlike every other component

1 participant