Typescript with Angular HttpClient ErrorType ...在调用类方法时不是函数
Posted
技术标签:
【中文标题】Typescript with Angular HttpClient ErrorType ...在调用类方法时不是函数【英文标题】:Typescript with Angular HttpClient ErrorType ... is not a function when calling class method 【发布时间】:2018-11-04 20:53:42 【问题描述】:我在 typescript/angular 中遇到了一些奇怪的(对我来说)对象和类型的问题。
我有一些描述从远程 API 接收到的对象的类:
export class Point
lat:number;
lng:number;
name:string;
public doSomething()
console.log("doSomething called");
我正在使用HttpClient
从 API 获取对象:
constructor(private http:HttpClient)
getPointsAsync(callback: (points: Point[]) => )
this.http.get<Point[]>(`$environment.apiUrl/api/points`)
.subscribe(
(result: Point[]) =>
//do something with data
callback(result);
,
error => //some error handling
);
我的问题是,当我尝试在数组中的一个点上调用方法 doSomething
时
var firstPoint = points[0];
firstPoint.doSomething()
我在控制台上收到一些奇怪的错误:
ERROR TypeError: firstPoint.doSomething is not a function
我很久没有使用 Typescript 和 Angular,所以我假设我的代码有问题,但我找不到问题的答案。你能给我一些建议吗?
【问题讨论】:
【参考方案1】:问题是您实际上并没有从 Web 服务中获得 Point
的实例。你得到一个 JSON 对象,它有类字段,但没有方法。您可以使用实例化类并使用 Object.assign
将对象文字中的值分配给每个 Point
实例
getPointsAsync(callback: (points: Partial<Point>[]) => )
this.http.get<Point[]>(`$environment.apiUrl/api/points`)
.subscribe(
(result: Partial<Point>[]) =>
let points = result.map(p=> Object.assign(new Point(), p));
callback(points);
,
error => //some error handling
);
【讨论】:
感谢您的回答。我是否必须在需要特定类实例的每个请求中调用Object.assign
?或者也许可以将它移到其他地方,例如HttpInterceptor
?
@user3626048 我不知道另一种方法,你需要以某种方式传递构造函数(类型参数是不够的,因为它会在运行时被删除)【参考方案2】:
Object.assign()
将解决您当前的问题,但如果您有嵌套对象则不会。然后,您还必须为每个嵌套对象执行 Object.assign()
,如果您必须在代码库中的多个位置执行此操作,这可能会变得乏味。
我建议另一种选择:class-transformer 使用它,您可以使用注释标记嵌套字段,告诉编译器如何创建嵌套对象。有了这个,您只需要使用plainToClass()
方法来映射您的***对象,所有底层字段也将具有正确的类型/对象。
示例
假设我们有两个类:
class Parent
name: string;
child: Child;
public getText(): string
return 'parent text';
class Child
name: string;
public getText(): string
return 'child text';
第一种情况我们已经知道是行不通的:
let parentJson: any = name: 'parent name', child: name: 'child name';
let parent: Parent = parentJson; // note: compiler accepts this because parentJson is any.
// If we tried to assign the json structure directly to 'parent' it would fail because the compiler knows that the method getText() is missing!
console.log(parent.getText()); // throws the error that parent.getText() is not a function as expected
第二种情况使用Object.assign()
:
let parentJson: any = name: 'parent name', child: name: 'child name';
let parent: Parent = Object.assign(parentJson);
console.log(parent.getText()); // this works
console.log(parent.child.getText()); // throws error that parent.child.getText() is not a function!
要使其正常工作,我们必须执行以下操作:
let parentJson: any = name: 'parent name', child: name: 'child name';
let parent: Parent = Object.assign(parentJson);
parent.child = Object.assign(parentJson.child);
console.log(parent.getText()); // this works
console.log(parent.child.getText()); // this works
第三种情况与类转换器:
首先修改父类,以便定义子映射:
class Parent
name: string;
@Type(() => Child)
child: Child;
public getText(): string
return 'parent text';
然后你可以映射到父对象:
let parentJson: any = name: 'parent name', child: name: 'child name';
let parent: Parent = plainToClass(Parent, parentJson);
console.log(parent.getText()); // this works
console.log(parent.child.getText()); // this works
【讨论】:
以上是关于Typescript with Angular HttpClient ErrorType ...在调用类方法时不是函数的主要内容,如果未能解决你的问题,请参考以下文章
Angular 5 GET data with Observable and HttpClient - 从 Web API 获取数据
Building-Mobile-Apps-with-Ionic-2中文翻译工作
[Typescript] Improve Readability with TypeScript Numeric Separators when working with Large Numbers(