Skip to content

feat(protoc-gen-es): narrow JSON type for finite float/double fields#1399

Open
odsod wants to merge 1 commit intobufbuild:mainfrom
odsod:json-types-protovalidate-finite
Open

feat(protoc-gen-es): narrow JSON type for finite float/double fields#1399
odsod wants to merge 1 commit intobufbuild:mainfrom
odsod:json-types-protovalidate-finite

Conversation

@odsod
Copy link
Copy Markdown

@odsod odsod commented May 5, 2026

Summary

When json_types=protovalidate_finite is enabled and a float/double field has (buf.validate.field).{float,double}.finite = true, the generated JSON type is narrowed from number | "NaN" | "Infinity" | "-Infinity" to just number.

This follows the existing pattern of valid_types=protovalidate_required — reading protovalidate constraints at codegen time to produce tighter TypeScript types.

Example

message Metrics {
  double score = 1 [(buf.validate.field).double.finite = true];
  double ratio = 2;  // no constraint
}

Generated with json_types=protovalidate_finite:

export type MetricsJson = {
  score?: number;                                     // narrowed
  ratio?: number | "NaN" | "Infinity" | "-Infinity";  // unchanged
};

Option syntax

  • json_types=true — existing behavior, unchanged
  • json_types=protovalidate_finite — enables json types AND narrows finite-constrained fields

Changes

  • Extend minimal-validate.proto with FloatRules/DoubleRules (just the finite field) in the FieldRules.type oneof
  • Add isProtovalidateFinite() helper in valid-types.ts
  • Update fieldJsonType() in util.ts to return "number" when the constraint is detected
  • Support compound json_types option values (analogous to valid_types=protovalidate_required+legacy_required)
  • Add test proto, generated output, and type-level test

Test plan

  • Run npm run generate in packages/protobuf-test to regenerate with the updated plugin
  • Verify npm test passes (type-level tests assert narrowed types)
  • Verify json_types=true still works identically (no regression)

Add `json_types=protovalidate_finite` option that narrows the generated
JSON type for float/double fields from
`number | "NaN" | "Infinity" | "-Infinity"` to `number` when the field
has `(buf.validate.field).{float,double}.finite = true`.

- Extend minimal-validate.proto with FloatRules/DoubleRules messages
  containing the `finite` field
- Add `isProtovalidateFinite()` helper to detect the constraint
- Update `fieldJsonType()` to return `"number"` when finite is detected
- Support compound `json_types` option values (e.g.
  `json_types=protovalidate_finite`)
- `json_types=true` continues to work unchanged (no breaking change)
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 5, 2026

CLA assistant check
All committers have signed the CLA.

@odsod
Copy link
Copy Markdown
Author

odsod commented May 6, 2026

@timostamm I submitted this mostly to check whether you think this is a good idea. The context on why we would like this is that we are using Vercel SSR + Edition 2023 (generated types always have a prototype chain for presence tracking), so to avoid serialization issues we use the Json types as the canonical types in our frontend. This improves the main friction point for us in using the generated Json types (not having to use functions that typecast away NaN and Inf when working with floats).

What do you think - would something like this make sense?

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