Skip to content

Add support for @discriminated unions - #6050

Draft
Joel Hendrix (jhendrixMSFT) wants to merge 1 commit into
Azure:mainfrom
jhendrixMSFT:go-discriminated
Draft

Joel Hendrix (jhendrixMSFT) wants to merge 1 commit into
Azure:mainfrom
jhendrixMSFT:go-discriminated

Conversation

@jhendrixMSFT

Copy link
Copy Markdown
Member

The generated code is polymorphic like for Discriminator types, the only difference is there's no fallback base type.

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • ✅ @azure-tools/typespec-go
Show changes

@azure-tools/typespec-go - feature ✏️

Add support for @discriminated unions with inline or object-envelope serialization and custom property names, including collection responses and generated samples. Unions without a base model generate variant interfaces that return an unmarshalling error for unknown or missing discriminator values instead of falling back to a base model.

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

📦 Package size report

1 package changed size, +3.21 KB (+0.0%) packed overall.

Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-go 303.39 KB → 306.60 KB +3.21 KB (+1.1%) 🔴 1.55 MB → 1.57 MB +20.61 KB (+1.3%) 🔴
13 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/azure-http-specs 155.02 KB → 155.02 KB — 1.27 MB → 1.27 MB —
@azure-tools/typespec-autorest 88.65 KB → 88.65 KB — 427.94 KB → 427.94 KB —
@azure-tools/typespec-autorest-canonical 7.42 KB → 7.42 KB — 26.00 KB → 26.00 KB —
@azure-tools/typespec-azure-core 144.66 KB → 144.66 KB — 771.39 KB → 771.39 KB —
@azure-tools/typespec-azure-examples 96.99 KB → 96.99 KB — 487.04 KB → 487.04 KB —
@azure-tools/typespec-azure-portal-core 36.33 KB → 36.33 KB — 243.09 KB → 243.09 KB —
@azure-tools/typespec-azure-resource-manager 210.18 KB → 210.18 KB — 1.26 MB → 1.26 MB —
@azure-tools/typespec-azure-rulesets 6.21 KB → 6.21 KB — 38.47 KB → 38.47 KB —
@azure-tools/typespec-client-generator-core 264.53 KB → 264.53 KB — 1.40 MB → 1.40 MB —
@azure-tools/typespec-java 20.23 MB → 20.23 MB — 22.53 MB → 22.53 MB —
@azure-tools/typespec-metadata 15.88 KB → 15.88 KB — 62.08 KB → 62.08 KB —
@azure-tools/typespec-python 42.66 KB → 42.66 KB — 166.15 KB → 166.15 KB —
@azure-tools/typespec-ts 551.24 KB → 551.24 KB — 2.76 MB → 2.76 MB —

Packed = gzipped .tgz published to npm. Unpacked = total extracted size. 🆕 added, 🗑️ removed. Packages from the core/ submodule are not included.
🔴 grew · 🟢 shrank — only changes of at least 512 B and 0.5% are marked.

@pkg-pr-new

pkg-pr-new Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-go@6050

commit: a7e9906

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Go emitter diff

Baseline gh:9f3187901c0ef5015eb0d8eb4b0151166cd79135 vs this PR.

Diff summary: 39 file(s), +2967 / -3

Rendered diff: inline on the run summary, or the emitter-diff-go-html artifact.

Informational check (core/eng/emitter-diff); does not block the PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Union collection responses can fail generation or decoding due to missing union naming and discriminator-aware handling, while string-encoded numeric union examples produce uncompilable Go samples.

2 open issues
What changed in this PR

Adds Go emitter support for @discriminated unions using polymorphic interfaces and variant models. Unions without a base model reject unknown discriminator values rather than falling back to a base type.

Changes:

  • Supports inline and object-envelope variants, custom property names, and example generation.
  • Updates polymorphic code generation and fake-server handling.
  • Adds scenario baselines, adaptation tests, and Spector coverage.
File Description
packages/​typespec-go/​test/​unittest/​type-adaptation.test.ts Tests union interface and variant name collisions.
packages/​typespec-go/​test/​unittest/​scenarios/​discriminated-unions.md Adds generated baselines for unions, examples, and hierarchies.
packages/​typespec-go/​test/​unittest/​scenario-suites/​discriminated-unions.test.ts Registers the union scenario suite.
packages/​typespec-go/​test/​unittest/​scenario-runner.ts Enables union inheritance in test fixtures.
packages/​typespec-go/​test/​unittest/​example-adaptation.test.ts Tests nested example values and invalid discriminators.
packages/​typespec-go/​test/​http-specs/​type/​union/​disriminatedgroup/​discriminatednoenvelopedefault_client_test.go Tests default inline union requests and responses.
packages/​typespec-go/​test/​http-specs/​type/​union/​disriminatedgroup/​discriminatednoenvelopecustomdiscriminator_client_test.go Tests inline unions with a custom discriminator.
packages/​typespec-go/​test/​http-specs/​type/​union/​disriminatedgroup/​discriminatedenvelopeobjectdefault_client_test.go Tests default object-envelope unions.
packages/​typespec-go/​test/​http-specs/​type/​union/​disriminatedgroup/​discriminatedenvelopeobjectcustomproperties_client_test.go Tests custom envelope property names.
packages/​typespec-go/​test/​http-specs/​type/​union/​disriminatedgroup/​discriminated_client_test.go Tests invalid tags, null responses, serialization, and fake round trips.
packages/​typespec-go/​src/​tcgcadapter/​types.ts Adapts unions into interfaces and concrete variants.
packages/​typespec-go/​src/​tcgcadapter/​clients.ts Adapts union responses and raw example values.
packages/​typespec-go/​src/​codemodel/​type.ts Makes polymorphic interface base models optional.
packages/​typespec-go/​src/​codegen/​fake/​servers.ts Preserves intermediate clients needed for nested server dispatch.
packages/​typespec-go/​src/​codegen/​core/​polymorphics.ts Emits decoding errors for unions without a fallback model.
packages/​typespec-go/​src/​codegen/​core/​models.ts Adds marker methods for union variants.
packages/​typespec-go/​src/​codegen/​core/​interfaces.ts Generates union interfaces without base-model accessors.
packages/​typespec-go/​src/​codegen/​core/​helpers.ts Handles interfaces without base models during serialization traversal.
packages/​typespec-go/​src/​codegen/​core/​example.ts Selects a concrete variant for generated placeholder examples.
packages/​typespec-go/​spector.config.http.yaml Enables discriminated-union Spector scenarios.
.chronus/​changes/​main-2026-10-6-13-52-58.md Documents the new Go emitter capability.

Review effort: Balanced

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Helper discovery skips AnyResult response types, potentially leaving generated packages uncompilable, while discriminator decoding still fails for nested collections, fake request bodies, additional properties, and whitespace-padded null.

5 open issues
2 resolved since last review

Review effort: Balanced

if (interfaceType.rootType) {
text += `${indent.get()}b = &${prefix}${interfaceType.rootType.name}{}\n`;
} else {
text += `${indent.get()}return nil, fmt.Errorf("unrecognized discriminator value %v for ${interfaceType.name}", m["${interfaceType.discriminatorField}"])\n`;
return unmarshallerText;
}
if (format === "JSON" || format === "XML") {
if (format === "JSON" && (go.isSlice(type, "interface") || go.isMap(type, "interface"))) {
Comment on lines +479 to +480
if (type.discriminatedOptions && !this.getSseMetadata(type)) {
return this.getDiscriminatedUnion(type);
modelType.fields.push(
new go.ModelField("AdditionalProperties", addlPropsType, "", annotations),
);
fields.push(new go.ModelField("AdditionalProperties", addlPropsType, "", annotations));
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:go Issues for @azure-tools/typespec-go emitter label Nov 10, 2026
The generated code is polymorphic like for @Discriminator types, the
only difference is there's no fallback base type.

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

emitter:go Issues for @azure-tools/typespec-go emitter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants