Skip to content

fix(node): tighten StateSelector to typed behavior keys#3683

Merged
Apollon77 merged 3 commits intomainfrom
fix/state-selector-typed-keys
May 4, 2026
Merged

fix(node): tighten StateSelector to typed behavior keys#3683
Apollon77 merged 3 commits intomainfrom
fix/state-selector-typed-keys

Conversation

@Apollon77
Copy link
Copy Markdown
Collaborator

@Apollon77 Apollon77 commented May 4, 2026

Summary

  • Resolves TODO from 2d9d35fStateSelector<T> now produces typed attribute keys per behavior for concrete EndpointType.For<T> callers (autocomplete + rejection of unknown attribute names) while keeping RawBehaviorSelection as the fallback for unbound generic T extends EndpointType.
  • Discriminator string extends K inside the mapped type detects the widened-key case (index-sig path) vs the narrow literal-keyed case from MapOf<>. No changes to SupportedBehaviors itself.
  • Adds a @ts-expect-error type-level test asserting unknown attribute keys are rejected.

The earlier TODO claimed the SupportedBehaviors = Record<string, Behavior.Type> index signature blocked the tightening; investigation showed concrete EndpointType.For<T>["behaviors"] is already the literal MapOf<> shape (no index sig), so keyof is narrow there. The conditional handles both shapes.

🤖 Generated with Claude Code

Resolves the TODO from 2d9d35f. The previous comment claimed the
SupportedBehaviors index signature blocked tightening, but concrete
EndpointType.For<T> already preserves the literal MapOf<> shape with
narrow keys. Use a `string extends K` discriminator inside StateSelector
so concrete typed endpoints get BehaviorSelection<BehaviorAt<T,K>>
(typed attribute keys, autocomplete, rejection of unknown keys), and
unbound `T extends EndpointType` falls back to RawBehaviorSelection.

Adds a @ts-expect-error type-level test asserting unknown attribute
keys are rejected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 4, 2026 06:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens the @matter/node endpoint type helpers so StateSelector<T> can use concrete behavior state keys when the caller has a fully typed EndpointType.For<T>, while still falling back to raw string selections for widened generic endpoint types. It improves the developer experience around Endpoint.get() typing without changing the runtime behavior of endpoint reads.

Changes:

  • Refines StateSelector<T> to select BehaviorSelection for literal behavior maps and keep RawBehaviorSelection for generic/index-signature behavior maps.
  • Removes the old TODO in Endpoint.ts by implementing the type-level narrowing directly.
  • Adds a compile-time @ts-expect-error assertion to verify unknown attribute keys are rejected for a concretely typed endpoint.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/node/src/endpoint/Endpoint.ts Updates the StateSelector<T> type to distinguish literal behavior keys from widened generic behavior maps.
packages/node/test/endpoint/EndpointGetTypesTest.ts Adds a type-level regression test for rejecting invalid attribute keys on typed endpoint selections.

Comment thread packages/node/src/endpoint/Endpoint.ts
Adds a type-level equality assertion that the `string extends K`
fallback branch of `StateSelector<T>` resolves to `RawBehaviorSelection`
for unbound `T extends EndpointType`, plus a runtime-shape assertion
that arbitrary string-keyed attribute lists remain assignable. Closes
the regression gap noted by Copilot review on PR #3683 — without this,
a refactor that drops or reorders the fallback branch could silently
break generic callers that relied on raw string selections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread packages/node/test/endpoint/EndpointGetTypesTest.ts
… path

Adds a type-level regression test that builds an endpoint via the actual
`EndpointType(...)` + `SupportedBehaviors(...)` + `MapOf<>` pipeline and
asserts: (a) `keyof behaviors` stays narrow to the literal id rather than
widening to `string`, and (b) `StateSelector<T>` accepts known State keys
and rejects unknown ones. Closes the gap noted by Copilot review on
PR #3683 — the previous tests only used a hand-built intersection
(`EndpointType & { behaviors: { fake: ... } }`) that would still pass
even if `EndpointType.For<T>` or `MapOf<T>` regressed for real, factory-
constructed endpoints.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Apollon77 Apollon77 merged commit e005cc1 into main May 4, 2026
40 checks passed
@Apollon77 Apollon77 deleted the fix/state-selector-typed-keys branch May 4, 2026 07:34
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.

2 participants