Alright guys, sorry about this question, as I know there are several already about Typescript when it compiles, but I'm encountering a flavor of this issue that I can't connect the dots with.
I'm trying to follow the Angular Tour of Heroes app, and am trying to finish it up with the chapter on Http, but my hero.service.ts
file outputs this error:
error TS2339: Property 'handleError' does not exist on type 'HeroService'
I know from the other questions on here that this most likely has something to do with how Typescript is configured, but there does not seem to be a consistent cause of this issue.
I'm not familiar enough with the idiosyncrasies of Typescript (or Angular) to troubleshoot the issue on my own.
My code right now reads like this:
CODE:
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Hero } from './hero';
@Injectable()
export class HeroService {
private heroesUrl: 'app/heroes'; //URL to web api
constructor(private http: Http) { }
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
}
getHeroesSlowly(): Promise<Hero[]> {
return new Promise<Hero[]>(resolve =>
setTimeout(resolve, 2000))
.then(() => this.getHeroes());
}
getHero(id: number): Promise<Hero> {
return this.getHeroes()
.then(heroes => heroes.find(hero => hero.id === id));
}
}
I am a bit puzzled by the fact that the error message says it can't find the property on 'HeroService' which is a class created within the program and is not a part of Typescript itself.
My systemjs.config.js
file looks like this:
SYSTEMJS.CONFIG:
/**
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular2-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
}
}
});
})(this);
My package.json
file reads like this:
PACKAGE.JSON:
{
"name": "angular2-quickstart",
"version": "1.0.0",
"scripts": {
"start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
"lite": "lite-server",
"postinstall": "typings install",
"tsc": "tsc",
"tsc:w": "tsc -w",
"typings": "typings"
},
"license": "ISC",
"dependencies": {
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
"@angular/forms": "2.0.0",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0",
"@angular/upgrade": "2.0.0",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27",
"zone.js": "^0.6.23",
"angular2-in-memory-web-api": "0.0.20",
"bootstrap": "^3.3.6"
},
"devDependencies": {
"concurrently": "^2.2.0",
"lite-server": "^2.2.2",
"typescript": "^2.0.2",
"typings":"^1.3.2"
}
}
If this question is a duplicate of some other version of this question that I'm not seeing feel free to direct me to it.
Thank you.
It was somewhat "mentioned" in the ToH tutorial, under the "Error Handling" part in the HTTP chapter. But it wasn't really clear that you needed to add this code part to your "hero.service.ts" file (at least if you tend to not fully read through text):
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
I just added it to the bottom inside the HeroService class and all worked. Hope it works for you as well :).
Property 'handleError' does not exist on type 'HeroService'
Functions are properties also.
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError); <=== Where is this? Not in HeroService
}
You need to define a handleError
method in the HeroService
class
handleError(error) {
// do something with error
}
Looks like you missed this part of the tutorial :-)
From the tutorial itself, you should add the following method to hero.service.ts
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
console.error(error);
this.log(`${operation} failed: ${error.message}`);
return of(result as T);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With