Skip to content

feat(analyzer): a const says what type a property has - #118

Merged
giraffesyo merged 1 commit into
canaryfrom
const-and-conditionals
Aug 21, 2026
Merged

feat(analyzer): a const says what type a property has#118
giraffesyo merged 1 commit into
canaryfrom
const-and-conditionals

Conversation

@giraffesyo

Copy link
Copy Markdown
Member

Two JSON Schema 2020-12 keywords, both reached only through 3.1.

const

kind: { const: dog }
Kind any     `json:"kind,omitempty"`   // before
Kind *string `json:"kind,omitempty"`

The const value states the type exactly, and 3.1 pins a discriminator this way: kind: {const: dog} is what a 3.0 spec wrote as enum: [dog]. So the tag of a discriminated union, the one property a caller reads to know which variant they have, came out as any.

Scalars map by their value: string, integer, number, boolean. A schema that states its own type keeps it, and a const that is not a scalar still resolves to any, since it says nothing a single Go type carries.

if / then / else

Dropped in silence, while dependentSchemas, which is the same kind of keyword, warns:

warning: if/then/else makes a shape depend on a value, which a Go struct cannot express, so it is not enforced

Not generated, for the reason in that sentence, and listed in the README's "Not supported" table beside its sibling.

Scale

Neither appears in the 3.1 specs I have to hand: ACTIVATE, its ledger service, and Mealie all use zero. This is correctness for the schema language 3.1 uses rather than a fix with a measured payoff, and the const half matters most for specs that write discriminators the 3.1 way.

Tests

internal/analyzer/schemas_const_test.go: each scalar const implies its type, a stated type wins, a non-scalar const stays any, and if/then/else warns exactly once per spec.

gofmt, golangci-lint, go vet ./..., and go test ./... pass.

A property declaring const and no type resolved to any, though the const
value states the type exactly: 3.1 pins a discriminator that way, writing
kind: {const: dog} where a 3.0 spec wrote enum: [dog], so the tag of a
discriminated union came out untyped.

A scalar const now types the property, and a schema that states its own type
keeps it. A const that is not a scalar still says nothing a Go type carries
on its own.

if/then/else is dropped for the same reason dependentSchemas is, a shape
that depends on a value is a validation rule rather than a type, and now
warns like its sibling instead of vanishing.
@giraffesyo
giraffesyo merged commit 82d2af7 into canary Aug 21, 2026
7 checks passed
@giraffesyo
giraffesyo deleted the const-and-conditionals branch August 21, 2026 19:29
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.

1 participant