Shawn
Shawn

Reputation: 5260

typescript arrow function parameter type safe

I have code that works fine when "noImplicitAny": false.

import ...;

@Injectable()
export class HeroService {
  private _cachedHeroes: Observable<Hero[]>; 
  private _init: boolean;
  private _heroesObserver: Observer<Hero[]>;
  private _heroObserver: Observer<Hero>;
  heroes$: Observable<Hero[]>; 
  hero$:   Observable<Hero>; 
  public _dataStore: { heroes: Hero[], hero: Hero };

  constructor (private http: Http) {
        this._init = true;
        this._dataStore = { heroes: [], hero: {_id: null, name: null} };
        this.heroes$ = new Observable((observer: any) =>  this._heroesObserver = observer).share();//.publishReplay(1).refCount();
        this.hero$   = new Observable((observer: any) =>  this._heroObserver = observer).share();
        this._baseUrl = 'http://localhost:8081/api/hero/';  
  }

  loadHero1(id: number) {
      this.hero$ = this._cachedHeroes.map(heroes => heroes.find(hero => {hero._id === id;})) 
                                     .catch(handleError)
                                     .subscribe( data => {  
                                                            this._dataStore.hero = data;
                                                            this._heroObserver.next(this._dataStore.hero);
                                                         },  
                                                  error => handleError('Could not load hero.')
                                               );
  }
  .......
}        

Since I want to make it type safe, I changed the tsconfig.json to "noImplicitAny": true.

Then I got the following error

[0] services/hero.service.ts(58,7): error TS2322: Type 'Subscription' is not assignable to type 'Observable<Hero>'.
[0]   Property '_isScalar' is missing in type 'Subscription'.
[1] [BS] File changed: dist\services\hero.js
[1] [BS] File changed: dist\services\common.js
[0] services/hero.service.ts(58,65): error TS2345: Argument of type '(hero: Hero) => void' is not assignable to parameter of type '(value: Hero, index: number, obj: Hero[]) => boolean'.
[0]   Type 'void' is not assignable to type 'boolean'.

Here are my questions

  1. How can I cast this._cachedHeroes.map().subscribe() from type Subscription to type Observable to resolve TS2322 error? I have tried <Observable<Hero[]>>.this._cachedHeroes.... but it did not work.
  2. How can I define the type for the argument to TypeScript arrow function to resolve TS2345 error? I have tried heroes.find( (hero: Hero) => {hero._id === id;}) but it didn't work.
  3. How can I change the explicit any to an Observer type in the below code?

    this.hero$ = new Observable((observer: any) => this._heroObserver = observer).share();

Any advice is appreciated.

Upvotes: 1

Views: 1518

Answers (2)

Shawn
Shawn

Reputation: 5260

With the help of @Günter Zöchbauer, I got this thing straighten out. So adding return statement will resolve the type mismatch. Here is the modified code that passed the compiler check.

  loadHero1(id: number) {
      this.hero$ = this._cachedHeroes.map(heroes => heroes.find(hero => { return hero._id === id; } )) 
                                     .catch(handleError)
                                     .map( (data : Hero) => {  
                                                            this._dataStore.hero = data;
                                                            this._heroObserver.next(this._dataStore.hero);
                                                            return data;
                                                         } 
                                                  //error => handleError('Could not load hero.')
                                               );
  }

Upvotes: 2

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657476

subscribe() returns a Subscription, not an Observable

If you change subscribe() to map() it should work

  loadHero1(id: number) {
    this.hero$ = this._cachedHeroes
    .map(heroes => heroes.find(hero => {hero._id === id;})) 
    .catch(handleError)
    .map( data => {  
      this._dataStore.hero = data;
      this._heroObserver.next(this._dataStore.hero);
    });
  }

or alternatively change

heroes$: Observable<Hero[]>; 

to

heroes$: Subscription;

but I don't think that is not the intention of your code.

Upvotes: 1

Related Questions