Skip to content

Commit 0942870

Browse files
Support serialization of object examples on unions (#5180)
This PR fixes this issue: * #4869 Currently, the `@typespec/openapi3` emitter supports `@example`s for `model`s, but outputs incorrect examples for `union`s. For example ([playground link](https://typespec.io/playground/?c=QGV4YW1wbGUoI3sgYTogMSB9KQptb2RlbCBBIHsKIMQUaW50ZWdlcjsKfQoK1C91bmlvbiBVxS9udW1iZXI6xQzMPSwKICB9xAV0ZXh0yB9zOiBzdHJpbmfHHn0K&e=%40typespec%2Fopenapi3&options=%7B%7D)): ```typespec @example(#{ a: 1 }) union U { number: { a: integer, }, text: { s: string, }, } ``` should output with `{ a: 1 }` as the example, but instead it is `{}`. The issue manifests in the `serializeValueAsJson` function in packages/compiler/src/lib/examples.ts, and occurs because the `resolveUnions` function in the same file fails to detect the appropriate union variant. With this PR, the example is emitted correctly. I've added a unit test to confirm this. --------- Co-authored-by: Christopher Radek <[email protected]>
1 parent 68228c8 commit 0942870

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: fix
3+
packages:
4+
- "@typespec/compiler"
5+
---
6+
7+
Fixed serialization of object examples on unions

packages/compiler/src/lib/examples.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ function resolveUnions(program: Program, value: ObjectValue, type: Type): Type |
7272
if (type.kind !== "Union") {
7373
return type;
7474
}
75+
const exactValueType = program.checker.getValueExactType(value);
7576
for (const variant of type.variants.values()) {
7677
if (
7778
ignoreDiagnostics(
7879
program.checker.isTypeAssignableTo(
79-
value.type.projectionBase ?? value.type,
80+
exactValueType ?? value.type.projectionBase ?? value.type,
8081
variant.type.projectionBase ?? variant.type,
8182
value,
8283
),

packages/compiler/test/decorators/examples.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ describe("@example", () => {
173173
});
174174

175175
describe("union", () => {
176-
it("valid", async () => {
176+
it("valid for union member reference", async () => {
177177
const { program, examples, target } = await getExamplesFor(`
178178
@example(test.a)
179179
@test union test {a: "a", b: "b"}
@@ -182,6 +182,30 @@ describe("@example", () => {
182182
expect(serializeValueAsJson(program, examples[0].value, target)).toEqual("a");
183183
});
184184

185+
it("valid for object value", async () => {
186+
const { program, examples, target } = await getExamplesFor(`
187+
model A {
188+
type: "a";
189+
a: string;
190+
}
191+
model B {
192+
type: "b";
193+
b: numeric;
194+
}
195+
196+
@example(#{
197+
type: "a",
198+
a: "a string",
199+
})
200+
@test union test {a: A, b: B}
201+
`);
202+
expect(examples).toHaveLength(1);
203+
expect(serializeValueAsJson(program, examples[0].value, target)).toEqual({
204+
type: "a",
205+
a: "a string",
206+
});
207+
});
208+
185209
it("emit diagnostic for unassignable value", async () => {
186210
const diagnostics = await diagnoseCode(`
187211
@example(1)

0 commit comments

Comments
 (0)