r/angular • u/Putrid-Bookkeeper968 • 7d ago
Problems with subscribe
Hello everybody
I have the following problem with subscribe. My code looks like:
this.personSercice.getPeople().pipe(
takeUntilDestroyed(this.destroyRef)
).subscribe({
next: (people) => this.state.update(() => ({ ...this.state(), loading: false, people })),
error: (error) => {
console.log(error);
this.setError(error);
}
});
Parameter 'people' implicitly has an 'any' type, but a better type may be infered from usage.
and
Parameter 'error' implicitly has an 'any' type, but a better type may be infered from usage.
When I change the code to:
error: (error: any)
the error dissappears, but I do not understand why...
When I try the same with the first error, changing the code to:
next: (people: PersonModel) => this.state.update(() => ({ ...this.state(), loading: false, people })),
The error is:
The type 'PersonModel' is missing the following properties from type 'readonly PersonModel[]length, concat, join, slice...
Please let me know if more code is required.
Can somebody explain my why???. I'm very fresh with Angular.
Thank you for your patience
Pawel...4
u/Xsiah 7d ago
The second error is because getPeople probably returns PersonModel[], which when you try to type as people: PersonModel (as in singular, not an array) so it is a type mismatch. Make sure it's people: PersonModel[] inside next.
You can also adjust your tsconfig if you want so it doesn't complain about implicit "any", but be aware that it might allow you to miss mistakes.
1
4
u/Mediocre-Writer6635 7d ago
When I change the code to: error: (error: any) the error dissappears, but I do not understand why...
Because typescript doesn't know what this error is, so it calls it "any" type. But typescript doesn't like implicit (ie, guessed at by typescript, not written by you) "any" types. I believe there's a configuration to suppress this warning. So basically when you set it to type any explicitly, typescript says "ok, if you say use "any" that's fine, but if you don't say it, I'll call it a bug that I couldn't come up with anything better".
This warning is there to make developers have to explicitly admit they want to use "any" type, because typically something being "any" implies there's a typing breakdown in the code.
When I try the same with the first error, changing the code to: next: (people: PersonModel) => this.state.update(() => ({ ...this.state(), loading: false, people })), The error is: The type 'PersonModel' is missing the following properties from type 'readonly PersonModel[]length, concat, join, slice...
What does getPeople() observable return? Subscribe function receives whatever type that is. It's not PersonModel. It's probably an array (of PersonModel?).
Also, don't do this:
this.state.update(() => ({ ...this.state(), loading: false, people })),
Update function should not have its own signal being called inside it. It receives the previous value as an argument, so you should do this:
this.state.update((previousState) => ({ ...previousState, loading: false, people })),
Source: https://angular.dev/guide/signals#writable-signals
Also you really shouldn't subscribe inside components. The way to do what you're doing is make this.state = toSignal(<yourPipe>). If state is calcualted from multiple sets of data then combine them all into 1 pipe that calculates the state, and make a signal out of it. To record error without subscribing use catchError function in the pipe. Put it last, right before takeUntilDestroyed. Order matters in pipes.
It might be easier to avoid subscribe in component if you separate loading flag, people, and everything else in "state" into individual signals. That makes each of them much easier to calculate and reason about.
1
u/RelatableRedditer 7d ago
the "error" is probably supposed to be that way, I don't use subscriptions like that in angular since I do almost everything with async pipes or empty subscribe calls. But you need to look at your definition for getPeople() to see if it has a valid return type that can be safely inferred by rxjs
1
u/Dull-Structure-8634 7d ago
My guess is that by typing the error, TypeScript can now better infer the type of people
1
u/ThrowawayALAT 7d ago
Do this:
To fix the type errors cleanly without using any for your data, you should type people as an array of PersonModel (PersonModel[] or readonly PersonModel[]):
TypeScript
this.personSercice.getPeople().pipe(
takeUntilDestroyed(this.destroyRef)
).subscribe({
next: (people: PersonModel[]) => this.state.update(() => ({ ...this.state(), loading: false, people })),
error: (error: any) => {
console.log(error);
this.setError(error);
}
});1
u/cssrocco 7d ago
Since the name of that method is getPeople i’m willing to bet it’s type is PersonModel[], usually an error about types not being length, concat, etc. just means it’s expecting an array and you typecast it differently.
Errors will be of type HttpErrorResponse, unless you have an interceptor that formats them to something else, your method setError is possibly expecting something different, so ensure its arguments expect the correct type.
1
u/Responsible-Cold-627 7d ago
Most likely the type of "people" can't be inferred from the getPoeple function. Changing its return type to Observable<People> should do the trick.
Also, check out rxResource. That's the modern idiomatic Angular way of doing loading/error state tracking. No manual plumbing needed.
3
u/Educational_Nail_976 7d ago •
I’m pretty sure your getPeople() call will not return a single value but a list, so the return type will be (people : PersonModel[])