[英]Angular production error: Property does not exist on type 'object'
I have an Angular 7 app that is retrieving data from two separate endpoints:我有一个 Angular 7 应用程序,它从两个独立的端点检索数据:
http://localhost:1337/sms
http://localhost:1337/total
I can successfully make a GET request to these endpoints in development.我可以在开发中成功地向这些端点发出 GET 请求。 However, I get the following error when I run
ng build --prod
:但是,当我运行
ng build --prod
时出现以下错误:
ERROR in src/app/app.component.html(20,29): : Property 'total' does not exist on type 'object'.
As a test I temporarily removed {{ total.total }}
from app.component.html, ran ng build --prod
again and it worked.作为测试,我暂时从 app.component.html 中删除了
{{ total.total }}
,再次运行ng build --prod
并且它起作用了。
Is this not the right way to make GET requests to two separate endpoints or am I doing something else incorrectly, perhaps in my Node server file?这不是向两个单独的端点发出 GET 请求的正确方法,还是我做的其他事情不正确,也许是在我的 Node 服务器文件中?
app.component.ts app.component.ts
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
signees: object;
total: object;
constructor(private http: HttpClient){}
ngOnInit(): void {
this.http.get('http://localhost:1337/sms').subscribe(
data => {
this.signees = data;
}
);
this.http.get('http://localhost:1337/total').subscribe(
data => {
this.total = data;
}
);
}
}
Relevant app.component.html code相关的app.component.html代码
<section class="page-section mx-auto">
<h3 class="text-center">{{ total.total }} people have signed the petition</h3>
<div class="container">
<div class="row">
<div class="col-sm-6 col-lg-3"
*ngFor="let signee of signees; index as i">
<div class="card">
<div class="card-body">
<p class="h2">{{ signee.name }}</p>
<ul class="signee-meta text-muted">
<li>#{{ i + 1 }}</li>
<li>{{ signee.date }}</li>
</ul>
</div>
</div>
</div>
</div><!-- row -->
</div><!-- container -->
</section>
/total
endpoint (MongoDB) /total
端点(MongoDB)
app.get('/total', (req, res) => {
collection.countDocuments({}, function(err, num) {
assert.equal(null, err);
res.send({total: num});
});
});
EDIT (added data structure)编辑(添加数据结构)
Data structure (MongoDB)数据结构(MongoDB)
{
"_id" : ObjectId("5c61e0b658261f10280b5b17"),
"name" : "Bill Kickok",
"number" : "+14950395584",
"date" : "2/11/19"
}
This error is thrown when you run ng build --prod
because behind the scenes this kind of build proccess works with Ahead Of Time compilation.运行
ng build --prod
时会抛出此错误,因为在幕后这种构建过程适用于提前编译。
Here's what happens on AOT based on angular documentation .以下是基于angular 文档的AOT 上发生的事情。
Detect template errors earlier
更早地检测模板错误
The AOT compiler detects and reports template binding errors during the build step before users can see them.
AOT 编译器在构建步骤期间检测并报告模板绑定错误,然后用户才能看到它们。
You get that error because you try to render a property of total object while you have declared total
as object
.因为你尝试呈现共有对象的属性,而你已经宣布你得到这个错误
total
为object
。
In order to get rid of this error you should either create an interface
for this variable.为了摆脱这个错误,你应该为这个变量创建一个
interface
。 eg例如
export interface Total {
total: number
// any other properties total might include
}
Then use this interface for type definition in your component like this:然后在您的组件中使用此接口进行类型定义,如下所示:
total: Total
In case you don't want to create an interface - which is a bad practice - you can define total as any
( total: any
).如果您不想创建接口 -这是一种不好的做法- 您可以将 total 定义为
any
( total: any
)。
Lastly, directly making the http
requests in your component is also a bad practice .最后,直接在组件中发出
http
请求也是一种不好的做法。 You should create a service, then add those methods
which are responsible for communicating with your backend, then inject that service in your component and call that method.您应该创建一个服务,然后添加那些负责与后端通信的
methods
,然后将该服务注入到您的组件中并调用该方法。
I would advise you to take further look at angular documentation .我建议您进一步查看angular 文档。
If possible, it would be a good idea to strongly type these properties, so instead of:如果可能,最好对这些属性进行强类型化,而不是:
signees: object;
total: object;
If would be:如果是:
signees: Signee[];
total: Total;
Where Signee
and Total
would be interfaces: Signee
和Total
是接口的地方:
export interface Signee {
id: number;
name: string;
date: string;
// ...
}
export interface Total{
id: number;
total: number;
// ...
}
NOTE: The above would match the JSON structure returned in data
(which is why someone asked what the structure of your data
looked like).注意:以上将匹配
data
返回的 JSON 结构(这就是为什么有人问你的data
结构是什么样的)。
And if total is just a single number you are receiving back, then it would just be:如果总数只是您收到的一个数字,那么它就是:
total: number;
And you would just bind to total
, not total.total
.而且你只会绑定到
total
,而不是total.total
。
You can then use this strong typing when you send the request to ensure that the response is appropriately shaped:然后,您可以在发送请求时使用这种强类型,以确保响应的形状适当:
this.http.get<Signee[]>('http://localhost:1337/sms').subscribe(
data => {
this.signees = data;
}
);
Notice the generic parameter specified in the code above.注意上面代码中指定的泛型参数。
you need start your object inside of constructor.你需要在构造函数中启动你的对象。
ex:前任:
constructor(private http: HttpClient){
total = new Total();
}
Total is your class. Total 是你的班级。 This is recomendate in angular.io.
这是 angular.io 中的推荐。 Start your VAR inside constructor.
在构造函数中启动您的 VAR。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.