Skip to content

fix(types): stop LabelValues distributing over label-name unions - #869

Open
sarankumar1325 wants to merge 1 commit into
prometheus:mainfrom
sarankumar1325:fix/label-values-union
Open

sarankumar1325 wants to merge 1 commit into
prometheus:mainfrom
sarankumar1325:fix/label-values-union

Conversation

@sarankumar1325

Copy link
Copy Markdown

Fixes #861

LabelValues<T> uses T as a naked type parameter in its conditional, so TypeScript distributes it over a union of label names. For labelNames: ['a', 'b'] the type becomes Partial<Record<'a', ...>> | Partial<Record<'b', ...>>. Writes still compile, but reading labels back does not:

const { values } = await counter.get();
values[0].labels.a; // TS2339: Property 'a' does not exist on type ...

This wraps both sides of the conditional in a tuple ([T] extends [NoLabelNameType]), so the label names stay one object type with every key. The no-label case (T = never) now resolves to Partial<Record<string, never>> as intended, instead of never.

Tests:

  • Added a case to test/typescript.ts that reads labels.a / labels.b from get() on a two-label counter, plus a @ts-expect-error for an undeclared label. tsc --project . fails on main with TS2339 and passes with this change.
  • npm run lint, npm run check-prettier and jest (651 tests) pass.
  • CHANGELOG entry under Unreleased.

LabelValues<T> used a naked type parameter in its conditional, so for
labelNames ['a', 'b'] it became a union of single-key objects and reading
labels back from get() failed to compile (values[0].labels.a). Wrap both
sides in a tuple so the label names stay one object type.

Fixes prometheus#861

Signed-off-by: sarankumar1325 <120080287+sarankumar1325@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

TypeScript: LabelValues distributes over label-name unions, so labels from get() lose all but one key

1 participant