Skip to content

fix(angular): correct the httpResource stability note and keep the hasValue guard - #3828

Draft
the-ult wants to merge 2 commits into
orval-labs:masterfrom
the-ult:fix/angular-httpresource-stale-experimental-tag
Draft

fix(angular): correct the httpResource stability note and keep the hasValue guard#3828
the-ult wants to merge 2 commits into
orval-labs:masterfrom
the-ult:fix/angular-httpresource-stale-experimental-tag

Conversation

@the-ult

@the-ult the-ult commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

What

Two problems in the generated Angular httpResource output.

1. The stability note is wrong. Every generated resource function carries:

/**
 * @experimental httpResource is experimental (Angular v19.2+)
 */

httpResource is annotated @experimental 19.2 in @angular/common up to Angular 21, and @publicApi 22.0 from Angular 22. The note is therefore wrong for current Angular.

2. toResourceState erases a type guard. Angular declares hasValue() on HttpResourceRef as a type predicate, and its documentation tells users to guard value() with it, because reading value() in an error state throws. The generated ResourceState flattened it:

readonly hasValue: () => boolean;

So value() stayed Pet | undefined after the guard, and the documented pattern did not typecheck.

Fix

Orval supports Angular 19.2 and later, so no stability claim is correct for the whole range. The note now gives the availability fact only:

/**
 * @remarks httpResource is available in Angular 19.2 and later.
 */

hasValue is now a predicate onto a new exported interface:

readonly hasValue: () => this is ResolvedResourceState<T>;

export interface ResolvedResourceState<T> extends ResourceState<T> {
  readonly value: Signal<Exclude<T, undefined>>;
}

Exclude<T, undefined> mirrors Angular's own overload rather than NonNullable, because a resource that holds null does have a value.

Two simpler shapes were tried first and both fail. this is ResourceState<NonNullable<T>> leaves value as Signal<T | undefined>. An intersection that overrides value also fails, because intersected call signatures behave as overloads and the first declared one wins. A sub-interface is what actually narrows.

Runtime behaviour does not change. The result is still assignable to a () => boolean consumer, so structural users such as ngrx-toolkit withResource keep working.

User-visible changes

Generated resource files carry the corrected note, and hasValue() now narrows value():

const state = toResourceState(showPetByIdResource(petId));
if (state.hasValue()) {
  state.value(); // Pet, was Pet | undefined
}

21 generated fixture and sample files change: 63 note replacements, and 19 files gain the ResolvedResourceState declaration. Two of the 21 are tag-split files that do not emit the state utilities.

Tests

packages/angular/src/http-resource.test.ts covers the emitted note and the declaration. The narrowing was verified against real generated output under Angular's strict tsconfig with Equal<> assertions: Pet | undefined before the guard, Pet after, and null preserved.

Verification

build:release, typecheck, lint, format:check, test, test:snapshots — all green. The root typecheck covers packages/*, so the generated output was typechecked separately through samples/angular-app/tsconfig.app.json.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added type-safe resource state narrowing through hasValue().
    • Resource values are now recognized as defined after confirming availability, improving TypeScript developer experience.
  • Documentation
    • Updated httpResource documentation to indicate availability in Angular 19.2 and later.
  • Tests
    • Updated documentation checks to reflect the new availability status.

…sValue guard

Every generated resource function carried
`@experimental httpResource is experimental (Angular v19.2+)`.
`httpResource` carries `@experimental 19.2` up to Angular 21 and
`@publicApi 22.0` from Angular 22, so the note is wrong for current
Angular. Orval supports Angular 19.2 and later, so a stability claim
cannot be correct for the whole range. The note now gives the
availability fact only:

    @remarks httpResource is available in Angular 19.2 and later.

`toResourceState` also erased a type guard. Angular declares
`hasValue()` on `HttpResourceRef` as a type predicate, and its
documentation tells users to guard `value()` with it, because reading
`value()` in an error state throws. The generated `ResourceState`
declared `hasValue: () => boolean`, so `value()` stayed
`T | undefined` after the guard.

`hasValue` is now a predicate onto a new `ResolvedResourceState<T>`,
which narrows `value` to `Signal<Exclude<T, undefined>>`. `Exclude`
mirrors Angular's own overload and keeps `null`, because a resource
that holds `null` does have a value. Runtime behaviour does not
change, and the shape is still assignable to a `() => boolean`
consumer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 7, 2026 17:44
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 217e746f-3781-4979-bb73-fa8801fcc388

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change documents httpResource as available in Angular 19.2 and later. It also adds ResolvedResourceState<T> and changes ResourceState.hasValue() into a type guard across the Angular implementation and sample applications.

Changes

Angular httpResource updates

Layer / File(s) Summary
Resolved resource state type guard
packages/angular/src/http-resource.ts, samples/angular-app/src/api/http-both/pets/pets.resource.ts, samples/angular-app/src/api/http-resource-zod/pets/pets.service.ts, samples/angular-app/src/api/http-resource/pets/pets.service.ts
ResourceState.hasValue() now narrows to ResolvedResourceState<T>. The resolved state exposes a value signal that excludes undefined.
Angular availability documentation
packages/angular/src/http-resource.ts, packages/angular/src/http-resource.test.ts, samples/angular-app/src/api/http-both/pets/pets.resource.ts, samples/angular-app/src/api/http-resource-zod/pets/pets.service.ts, samples/angular-app/src/api/http-resource/pets/pets.service.ts
Generated and sample documentation now states that httpResource is available in Angular 19.2 and later. The test verifies the new remark and absence of @experimental.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: angular

Suggested reviewers: luantaraschi

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the corrected stability note and preserved hasValue type guard, which are the main changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@the-ult
the-ult marked this pull request as draft August 7, 2026 17:46

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.

Pull request overview

Updates the Angular httpResource generator output to reflect current Angular API status and to preserve Angular’s hasValue() type-guard semantics when wrapping an HttpResourceRef into a flattened ResourceState helper.

Changes:

  • Replaces the generated @experimental JSDoc note with an availability-only @remarks note for Angular 19.2+.
  • Introduces ResolvedResourceState<T> and makes ResourceState<T>.hasValue() a this is ... type guard, implemented via toResourceState().
  • Updates Angular-related snapshots and sample generated outputs to match the new emitted types/docs.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/snapshots/angular/url-encode-parameters-http-resource/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/issue-3712-http-resource/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/issue-3705-http-resource/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/issue-3624/petstore.client.service.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-zod/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-zod-disabled/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-tags/pets.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-tags/health.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-request-extension-multi-content/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-multi-content/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-headers/endpoints.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-both-tags-split/pets/pets.resource.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
tests/snapshots/angular/http-resource-both-tags-split/health/health.resource.ts Snapshot updates for @remarks note + ResolvedResourceState/hasValue guard emission
samples/angular-app/src/api/http-resource/pets/pets.service.ts Sample generated output updated to new JSDoc note + state narrowing types
samples/angular-app/src/api/http-resource-zod/pets/pets.service.ts Sample generated output updated to new JSDoc note + state narrowing types
samples/angular-app/src/api/http-both/pets/pets.resource.ts Sample generated output updated to new JSDoc note + state narrowing types
samples/angular-app/snapshots/api/http-resource/pets/pets.service.ts Sample snapshot updated to new JSDoc note + state narrowing types
samples/angular-app/snapshots/api/http-resource-zod/pets/pets.service.ts Sample snapshot updated to new JSDoc note + state narrowing types
samples/angular-app/snapshots/api/http-both/pets/pets.resource.ts Sample snapshot updated to new JSDoc note + state narrowing types
packages/angular/src/http-resource.ts Generator source: emits @remarks note; emits ResolvedResourceState<T> and hasValue() as a type guard
packages/angular/src/http-resource.test.ts Updates the JSDoc annotation assertion for the generated resource header

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/angular/src/http-resource.test.ts
@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

@orval/angular

bun add https://pkg.pr.new/@orval/angular@c1e8017

@orval/axios

bun add https://pkg.pr.new/@orval/axios@c1e8017

@orval/core

bun add https://pkg.pr.new/@orval/core@c1e8017

@orval/effect

bun add https://pkg.pr.new/@orval/effect@c1e8017

@orval/fetch

bun add https://pkg.pr.new/@orval/fetch@c1e8017

@orval/hono

bun add https://pkg.pr.new/@orval/hono@c1e8017

@orval/mcp

bun add https://pkg.pr.new/@orval/mcp@c1e8017

@orval/mock

bun add https://pkg.pr.new/@orval/mock@c1e8017

orval

bun add https://pkg.pr.new/orval@c1e8017

@orval/query

bun add https://pkg.pr.new/@orval/query@c1e8017

@orval/solid-start

bun add https://pkg.pr.new/@orval/solid-start@c1e8017

@orval/swr

bun add https://pkg.pr.new/@orval/swr@c1e8017

@orval/zod

bun add https://pkg.pr.new/@orval/zod@c1e8017

commit: c1e8017

@the-ult the-ult left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

and fix the issues. Apply your recommended fixes

@the-ult the-ult left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fix the issues. Apply your recommended fixes

@melloware melloware added the angular Related to Angular generation issues label Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

angular Related to Angular generation issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants