Skip to content

fix(core): derive possible null value in rxResource stream params (#6…#68171

Open
surajy93 wants to merge 1 commit intoangular:mainfrom
surajy93:fix-core-null-rxresource
Open

fix(core): derive possible null value in rxResource stream params (#6…#68171
surajy93 wants to merge 1 commit intoangular:mainfrom
surajy93:fix-core-null-rxresource

Conversation

@surajy93
Copy link
Copy Markdown

When an optional params function returns undefined, Angular's rxResource internally defaults the params loader value to null at runtime. This change updates ResourceLoaderParams<R> to correctly allow null alongside the resolved type, ensuring developers get accurate TypeScript feedback when omitted.

Fixes #62724

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

When the params option is not provided to rxResource or it evaluates to undefined, the type of the params argument in the internal stream function is restricted to the strictly inferred type (e.g. Params), even though it resolves to null at runtime.

Issue Number: #62724

What is the new behavior?

The type inference for ResourceLoaderParams<R> correctly derives a potential null value in instances where undefined could be inferred from the original params option payload. This correctly aligns the TypeScript expectations within stream or loader functions to match the runtime behavior.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

N/A

@google-cla

This comment was marked as outdated.

@pullapprove pullapprove bot requested a review from atscott April 13, 2026 16:31
@angular-robot angular-robot bot added the area: core Issues related to the framework runtime label Apr 13, 2026
@ngbot ngbot bot added this to the Backlog milestone Apr 13, 2026
Comment thread packages/forms/signals/test/node/resource.spec.ts Outdated
@surajy93 surajy93 requested a review from JeanMeche April 13, 2026 17:42
@JeanMeche
Copy link
Copy Markdown
Member

JeanMeche commented Apr 13, 2026

It looks better.
Another example that still doesn't work:

const data = resource({
  params: () => Math.random() ? undefined : 'test',
  loader: ({ params }) => {
    console.log('> params', params); // string, should be string|undefined 
    return Promise.resolve('');
  },
});

@surajy93
Copy link
Copy Markdown
Author

surajy93 commented Apr 13, 2026

It looks better. Another example that still doesn't work:

const data = resource({
  params: () => Math.random() ? undefined : 'test',
  loader: ({ params }) => {
    console.log('> params', params); // string, should be string|undefined 
    return Promise.resolve('');
  },
});

It looks better. Another example that still doesn't work:

const data = resource({
  params: () => Math.random() ? undefined : 'test',
  loader: ({ params }) => {
    console.log('> params', params); // string, should be string|undefined 
    return Promise.resolve('');
  },
});

let me check and test it please provide all the test cases and details thank you

@JeanMeche
Copy link
Copy Markdown
Member

Also please check the CLA check. You're authoring your commits with 2 different names.

@surajy93
Copy link
Copy Markdown
Author

surajy93 commented Apr 13, 2026

const data = resource({
  params: () => Math.random() ? undefined : 'test',
  loader: ({ params }) => {
    console.log('> params', params); // string, should be string|undefined 
    return Promise.resolve('');
  },
});

@JeanMeche

loader should stay typed as string here, not string | undefined. When a params function is provided, Angular treats undefined as “no request” and leaves the resource idle, so the loader is not invoked for that branch. In other words, params() may return string | undefined, but loader only runs for the resolved, non-undefined case. The nullable case we’re fixing is different: it applies when the params option itself is omitted or explicitly undefined, because Angular uses an internal null sentinel there.`

Shorter version:

I don’t think this one should widen to \string | undefined. If params()returnsundefined, the resource goes idle and loaderis skipped, so insideloader the type should remain the non-undefined branch (string). The bug we’re fixing is the separate case where the paramsoption is omitted or explicitlyundefined, which currently flows a runtime null sentinel.

please comment or suggestion why do u think that it should be string |undefined?

@surajy93 surajy93 force-pushed the fix-core-null-rxresource branch 4 times, most recently from 6ee7218 to df0e61a Compare April 13, 2026 20:14
@google-cla google-cla bot added cla: yes and removed cla: no labels Apr 13, 2026
@surajy93
Copy link
Copy Markdown
Author

surajy93 commented Apr 13, 2026

@JeanMeche apart the this edge cases everything look fine can you please take a look

@JeanMeche
Copy link
Copy Markdown
Member

Yeah you're right, my bad for that bad example.

Something else.
The generics are somehow not ideal.

In your test you have:

    const res = resource<string, string>({
      loader: async ({params}) => {
        seenParams = params;
        return 'foo';
      },
      injector: TestBed.inject(Injector),
    });

which should arguably have a single generic (since the request is not defined).

    const res = resource<string>({
      loader: async ({params}) => {
        seenParams = params;
        return 'foo';
      },
      injector: TestBed.inject(Injector),
    });

@surajy93

This comment was marked as outdated.

@surajy93 surajy93 force-pushed the fix-core-null-rxresource branch from afd1329 to d4e5368 Compare April 14, 2026 08:32
@google-cla google-cla bot added cla: no and removed cla: yes labels Apr 14, 2026
@surajy93 surajy93 force-pushed the fix-core-null-rxresource branch 3 times, most recently from 98c8099 to 7560a7e Compare April 14, 2026 08:44
@google-cla google-cla bot added cla: yes and removed cla: no labels Apr 14, 2026
surajy93

This comment was marked as outdated.

@surajy93 surajy93 force-pushed the fix-core-null-rxresource branch from 7560a7e to 4b58de4 Compare April 14, 2026 11:30
Copy link
Copy Markdown
Author

@surajy93 surajy93 left a comment

Choose a reason for hiding this comment

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

I have fix the test failed can you please again rerun the pipeline @JeanMeche

Comment thread packages/core/src/resource/resource.ts Outdated
@JeanMeche
Copy link
Copy Markdown
Member

I would also expect test that show that the typings are correct here.

@google-cla google-cla bot added cla: no and removed cla: yes labels Apr 15, 2026
@surajy93 surajy93 force-pushed the fix-core-null-rxresource branch from 1370f6e to e314c24 Compare April 15, 2026 13:17
@google-cla google-cla bot added cla: yes and removed cla: no labels Apr 15, 2026
Copy link
Copy Markdown
Author

@surajy93 surajy93 left a comment

Choose a reason for hiding this comment

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

@JeanMeche i have cover all the test cases and revert the run time code as mention ,
example below :
//params ommitted
resource1 = resource({
loader: async ({params}) => {
console.log(params); // {} | null | undefined
return 'hello';
}
})

paramsSignal = signal<Params | undefined>(undefined);

// params are optional
resource2 = resource({
params: this.getParams(),
loader: async ({params}) => {
console.log(params); // string | undefined
return 'hello';
}
})

resource3 = rxResource({
params: this.getParams(),
stream: ({params}) => {
console.log(params); // string | undefined
return of(params ? id=${params} : 'no id');
}
})

resource4 = resource({
params: () => 'test',
loader: async ({params}) => {
console.log(params) // string
return 'hello'
}
})

resource5 = resource({
params: () => 0,
loader: async ({params}) => {
console.log(params) // number
return 'hello'
}
})

resource6 =rxResource({
params: () => 'test',
stream: ({params}) => {
console.log(params) // string
return of('hello')
}
})

resource7 = rxResource({
params: () => 0,
stream: ({params}) => {
console.log(params) // number
return of('hello')
}
})

getParams(): (() => string) | undefined {
return Math.random() > 0.5 ? () => 'test' : undefined;
}

please review again and provide the feedback :)

Comment thread packages/core/src/resource/api.ts Outdated
Comment thread packages/core/rxjs-interop/src/rx_resource.ts Outdated
@JeanMeche JeanMeche removed the request for review from atscott April 15, 2026 13:39
Copy link
Copy Markdown
Author

@surajy93 surajy93 left a comment

Choose a reason for hiding this comment

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

I have resolve the comment issue mention @JeanMeche please review again

@surajy93 surajy93 requested a review from JeanMeche April 15, 2026 14:17
*
* @experimental 19.0
* @see [Async reactivity with resources](guide/signals/resource)
*/
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.

I don't think we should delete the tsDocs file we have (similar to another one we have above)

@JeanMeche JeanMeche force-pushed the fix-core-null-rxresource branch from 900fe3c to b8f4436 Compare April 15, 2026 16:13
@JeanMeche
Copy link
Copy Markdown
Member

I have squashed & pushed something that is simpler and more correct. PTAL and let me know what you think :)

@JeanMeche JeanMeche force-pushed the fix-core-null-rxresource branch from b8f4436 to 477c9fa Compare April 15, 2026 16:14
Comment thread packages/core/src/resource/api.ts
@JeanMeche JeanMeche force-pushed the fix-core-null-rxresource branch from 477c9fa to 4076690 Compare April 15, 2026 16:36
When the params is undefined or returns undefined, the param of the loader/stream gets the type `never`.

fixes angular#68167
@JeanMeche JeanMeche force-pushed the fix-core-null-rxresource branch from 4076690 to b8d5269 Compare April 15, 2026 16:37
@surajy93
Copy link
Copy Markdown
Author

surajy93 commented Apr 15, 2026

I have squashed & pushed something that is simpler and more correct. PTAL and let me know what you think :)

yes, it looks good, tested and working fine and sorry next time i will do better and thanks you for your patience and review :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Issues related to the framework runtime cla: yes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rxResource params field type in stream function doesn't derive possible null value

3 participants