Skip to content

fix(typescript-fetch): add samples for not enum - #25135

Merged
wing328 merged 7 commits into
masterfrom
AndreyVMarkelov-andreymarkelov/fix-typescript-fetch-not-enum
Oct 6, 2026
Merged

wing328 merged 7 commits into
masterfrom
AndreyVMarkelov-andreymarkelov/fix-typescript-fetch-not-enum

Conversation

@wing328

@wing328 wing328 commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

a follow up pr to #25095

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Enforces OpenAPI 3.1 not: enum constraints in typescript-fetch type guards, so instanceOf* functions now reject properties that match an excluded value instead of accepting them.

  • Generates exclusion checks in modelGeneric.mustache for string not.enum values, including null and sanitized or renamed property names.
  • Skips non-string exclusions such as numbers and booleans.
  • Adds a test spec and generated samples covering tagged unions, nullable exclusions, sanitized names, and multiple exclusions.

Written for commit 998828a. Summary will update on new commits.

Review in cubic

@wing328 wing328 changed the title Andrey v markelov andreymarkelov/fix typescript fetch not enum fix(typescript-fetch): enforce not enum in type guards Oct 6, 2026
@wing328
wing328 marked this pull request as ready for review October 6, 2026 04:15

@cubic-dev-ai cubic-dev-ai Bot 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.

11 issues found across 31 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MultipleExcluded.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MultipleExcluded.md:18">
P2: This example assigns `null` to `kind`, but `MultipleExcluded.kind` is an optional `string`, so the snippet fails under `strictNullChecks`; use an allowed string such as `"other"`.</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/NullableExcluded.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/NullableExcluded.md:18">
P2: This example uses a value that `instanceOfNullableExcluded` rejects; use an allowed value such as `"other"` so the documented instance passes the guard.</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts:15">
P3: This import line brings in four runtime date helpers that the file never uses. `TaggedUnion` is a type alias over `Known | Other` (both only have a plain `string` `kind`), and the file body only calls `instanceOf*`/`FromJSON*`/`ToJSON*`. The codegen imports these helpers only when `x-hasDateVars` is set — per the guard in `modelGeneric.mustache` and the comment in `TypeScriptFetchClientCodegen.java` that a model without dates should not import them — so a oneOf type-alias triggered the flag spuriously. Remove the unused import (or fix the `x-hasDateVars` computation so oneOf alias models without date vars don't emit it).</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/TaggedUnion.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/TaggedUnion.md:18">
P3: This example fails its `satisfies TaggedUnion` check in projects with `strictNullChecks`, because both union branches require a string `kind`. Use a valid string such as `"other"`.</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/Other.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/Other.md:18">
P2: This example does not satisfy `Other` when `strictNullChecks` is enabled because `kind` is declared as `string`. Use a valid string value such as `"other"`.</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/SanitizedExcluded.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/SanitizedExcluded.md:18">
P2: This example does not type-check because `filePath` is declared as `string`. Use a valid string value, such as `""`.</violation>
</file>

<file name="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java">

<violation number="1" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java:810">
P2: A `not: { enum: [null] }` exclusion is skipped when the nested enum has no string type, so nullable properties still pass `instanceOf` for `null`. Remove the `not.isString` gate; the loop already filters out non-string exclusions.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache:56">
P2: For renamed properties, this rejects the object when either alias is excluded, even if the other alias contains the valid generated property value. Apply the check to the same alias selected as the property value instead of rejecting on either key.</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MixedExcluded.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MixedExcluded.md:18">
P2: `MixedExcluded.kind` is `kind?: string`, so this example fails under `strictNullChecks` because `null` is not assignable. Use an allowed string or omit the optional property.</violation>

<violation number="2" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MixedExcluded.md:19">
P3: This example requires TypeScript 4.9 syntax, but the generated package allows TypeScript `^4.0`. Replace `satisfies` with a type annotation so users on TypeScript 4.0–4.8 can compile the example.</violation>
</file>

<file name="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/Known.md">

<violation number="1" location="samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/Known.md:18">
P2: This example fails `satisfies Known` with `strictNullChecks` enabled: `Known.kind` is the literal type `'known'`, but this assigns `null`. Use `"known"` so the documented snippet type-checks.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic


// TODO: Update the object below with actual values
const example = {
"kind": null,

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.

P2: This example assigns null to kind, but MultipleExcluded.kind is an optional string, so the snippet fails under strictNullChecks; use an allowed string such as "other".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MultipleExcluded.md, line 18:

<comment>This example assigns `null` to `kind`, but `MultipleExcluded.kind` is an optional `string`, so the snippet fails under `strictNullChecks`; use an allowed string such as `"other"`.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies MultipleExcluded
+
</file context>
Suggested change
"kind": null,
"kind": "other",


// TODO: Update the object below with actual values
const example = {
"kind": null,

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.

P2: This example uses a value that instanceOfNullableExcluded rejects; use an allowed value such as "other" so the documented instance passes the guard.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/NullableExcluded.md, line 18:

<comment>This example uses a value that `instanceOfNullableExcluded` rejects; use an allowed value such as `"other"` so the documented instance passes the guard.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies NullableExcluded
+
</file context>
Suggested change
"kind": null,
"kind": "other",


// TODO: Update the object below with actual values
const example = {
"kind": null,

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.

P2: This example does not satisfy Other when strictNullChecks is enabled because kind is declared as string. Use a valid string value such as "other".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/Other.md, line 18:

<comment>This example does not satisfy `Other` when `strictNullChecks` is enabled because `kind` is declared as `string`. Use a valid string value such as `"other"`.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies Other
+
</file context>
Suggested change
"kind": null,
"kind": "other",


// TODO: Update the object below with actual values
const example = {
"filePath": null,

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.

P2: This example does not type-check because filePath is declared as string. Use a valid string value, such as "".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/SanitizedExcluded.md, line 18:

<comment>This example does not type-check because `filePath` is declared as `string`. Use a valid string value, such as `""`.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "filePath": null,
+} satisfies SanitizedExcluded
+
</file context>

public ExtendedCodegenProperty fromProperty(String name, Schema p, boolean required) {
CodegenProperty cp = super.fromProperty(name, p, required);
CodegenProperty not = cp.getComposedSchemas() == null ? null : cp.getComposedSchemas().getNot();
if (not != null && not.isString && (not.isEnum || not.isEnumRef)

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.

P2: A not: { enum: [null] } exclusion is skipped when the nested enum has no string type, so nullable properties still pass instanceOf for null. Remove the not.isString gate; the loop already filters out non-string exclusions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java, line 810:

<comment>A `not: { enum: [null] }` exclusion is skipped when the nested enum has no string type, so nullable properties still pass `instanceOf` for `null`. Remove the `not.isString` gate; the loop already filters out non-string exclusions.</comment>

<file context>
@@ -805,6 +806,28 @@ public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, S
     public ExtendedCodegenProperty fromProperty(String name, Schema p, boolean required) {
         CodegenProperty cp = super.fromProperty(name, p, required);
+        CodegenProperty not = cp.getComposedSchemas() == null ? null : cp.getComposedSchemas().getNot();
+        if (not != null && not.isString && (not.isEnum || not.isEnumRef)
+                && not.allowableValues != null && not.allowableValues.get("values") instanceof List) {
+            StringJoiner comparisons = new StringJoiner(" || ");
</file context>
Suggested change
if (not != null && not.isString && (not.isEnum || not.isEnumRef)
if (not != null && (not.isEnum || not.isEnumRef)


// TODO: Update the object below with actual values
const example = {
"kind": null,

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.

P2: MixedExcluded.kind is kind?: string, so this example fails under strictNullChecks because null is not assignable. Use an allowed string or omit the optional property.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MixedExcluded.md, line 18:

<comment>`MixedExcluded.kind` is `kind?: string`, so this example fails under `strictNullChecks` because `null` is not assignable. Use an allowed string or omit the optional property.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies MixedExcluded
+
</file context>
Suggested change
"kind": null,
"kind": "other",


// TODO: Update the object below with actual values
const example = {
"kind": null,

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.

P2: This example fails satisfies Known with strictNullChecks enabled: Known.kind is the literal type 'known', but this assigns null. Use "known" so the documented snippet type-checks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/Known.md, line 18:

<comment>This example fails `satisfies Known` with `strictNullChecks` enabled: `Known.kind` is the literal type `'known'`, but this assigns `null`. Use `"known"` so the documented snippet type-checks.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies Known
+
</file context>
Suggested change
"kind": null,
"kind": "known",

* Do not edit the class manually.
*/

import { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';

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.

P3: This import line brings in four runtime date helpers that the file never uses. TaggedUnion is a type alias over Known | Other (both only have a plain string kind), and the file body only calls instanceOf*/FromJSON*/ToJSON*. The codegen imports these helpers only when x-hasDateVars is set — per the guard in modelGeneric.mustache and the comment in TypeScriptFetchClientCodegen.java that a model without dates should not import them — so a oneOf type-alias triggered the flag spuriously. Remove the unused import (or fix the x-hasDateVars computation so oneOf alias models without date vars don't emit it).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/src/models/TaggedUnion.ts, line 15:

<comment>This import line brings in four runtime date helpers that the file never uses. `TaggedUnion` is a type alias over `Known | Other` (both only have a plain `string` `kind`), and the file body only calls `instanceOf*`/`FromJSON*`/`ToJSON*`. The codegen imports these helpers only when `x-hasDateVars` is set — per the guard in `modelGeneric.mustache` and the comment in `TypeScriptFetchClientCodegen.java` that a model without dates should not import them — so a oneOf type-alias triggered the flag spuriously. Remove the unused import (or fix the `x-hasDateVars` computation so oneOf alias models without date vars don't emit it).</comment>

<file context>
@@ -0,0 +1,77 @@
+ * Do not edit the class manually.
+ */
+
+import { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime';
+import type { Known } from './Known';
+import {
</file context>


// TODO: Update the object below with actual values
const example = {
"kind": null,

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.

P3: This example fails its satisfies TaggedUnion check in projects with strictNullChecks, because both union branches require a string kind. Use a valid string such as "other".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/TaggedUnion.md, line 18:

<comment>This example fails its `satisfies TaggedUnion` check in projects with `strictNullChecks`, because both union branches require a string `kind`. Use a valid string such as `"other"`.</comment>

<file context>
@@ -0,0 +1,34 @@
+
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies TaggedUnion
+
</file context>
Suggested change
"kind": null,
"kind": "other",

// TODO: Update the object below with actual values
const example = {
"kind": null,
} satisfies MixedExcluded

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.

P3: This example requires TypeScript 4.9 syntax, but the generated package allows TypeScript ^4.0. Replace satisfies with a type annotation so users on TypeScript 4.0–4.8 can compile the example.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/typescript-fetch/builds/oneOf-not-enum/docs/MixedExcluded.md, line 19:

<comment>This example requires TypeScript 4.9 syntax, but the generated package allows TypeScript `^4.0`. Replace `satisfies` with a type annotation so users on TypeScript 4.0–4.8 can compile the example.</comment>

<file context>
@@ -0,0 +1,34 @@
+// TODO: Update the object below with actual values
+const example = {
+  "kind": null,
+} satisfies MixedExcluded
+
+console.log(example)
</file context>

@cubic-dev-ai cubic-dev-ai Bot 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.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/others/go/oneof-not-enum/docs/EnumNullUnion.md">

<violation number="1" location="samples/client/others/go/oneof-not-enum/docs/EnumNullUnion.md:7">
P2: These lines document a `Kind` field and `SetKindNil`/`UnsetKind` methods on `EnumNullUnion`, but neither exists in the generated code. The source spec (`modules/openapi-generator/src/test/resources/3_1/go/oneof-not-enum.yaml`) defines `EnumNullUnion` as a `oneOf` of `NullableEnum` and `NullableExcludedEnum` — there is no `kind` property — and the committed `model_enum_null_union.go` only has `NullableEnum`/`NullableExcludedEnum` fields plus a `NullableEnumNullUnion` wrapper, with no `GetKind`/`SetKind`/`SetKindNil`/`UnsetKind` methods. The "update go" commit (253efd49) regenerated this doc against a stale/different spec, so the committed sample now documents APIs that do not compile. Regenerate the sample docs from the current spec so `EnumNullUnion.md` documents the actual oneOf members.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**Kind** | Pointer to **string** | | [optional]
**Kind** | Pointer to **NullableString** | | [optional]

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.

P2: These lines document a Kind field and SetKindNil/UnsetKind methods on EnumNullUnion, but neither exists in the generated code. The source spec (modules/openapi-generator/src/test/resources/3_1/go/oneof-not-enum.yaml) defines EnumNullUnion as a oneOf of NullableEnum and NullableExcludedEnum — there is no kind property — and the committed model_enum_null_union.go only has NullableEnum/NullableExcludedEnum fields plus a NullableEnumNullUnion wrapper, with no GetKind/SetKind/SetKindNil/UnsetKind methods. The "update go" commit (253efd4) regenerated this doc against a stale/different spec, so the committed sample now documents APIs that do not compile. Regenerate the sample docs from the current spec so EnumNullUnion.md documents the actual oneOf members.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/others/go/oneof-not-enum/docs/EnumNullUnion.md, line 7:

<comment>These lines document a `Kind` field and `SetKindNil`/`UnsetKind` methods on `EnumNullUnion`, but neither exists in the generated code. The source spec (`modules/openapi-generator/src/test/resources/3_1/go/oneof-not-enum.yaml`) defines `EnumNullUnion` as a `oneOf` of `NullableEnum` and `NullableExcludedEnum` — there is no `kind` property — and the committed `model_enum_null_union.go` only has `NullableEnum`/`NullableExcludedEnum` fields plus a `NullableEnumNullUnion` wrapper, with no `GetKind`/`SetKind`/`SetKindNil`/`UnsetKind` methods. The "update go" commit (253efd49) regenerated this doc against a stale/different spec, so the committed sample now documents APIs that do not compile. Regenerate the sample docs from the current spec so `EnumNullUnion.md` documents the actual oneOf members.</comment>

<file context>
@@ -4,7 +4,7 @@
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**Kind** | Pointer to **string** |  | [optional] 
+**Kind** | Pointer to **NullableString** |  | [optional] 
 
 ## Methods
</file context>

@wing328 wing328 changed the title fix(typescript-fetch): enforce not enum in type guards fix(typescript-fetch): add samples for not enum Oct 6, 2026
@wing328
wing328 merged commit 27eeca6 into master Oct 6, 2026
18 of 24 checks passed
@wing328
wing328 deleted the AndreyVMarkelov-andreymarkelov/fix-typescript-fetch-not-enum branch October 6, 2026 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants