由于 httpClient 响应数据数组抛出打字稿构建问题,无法构建 angular 应用程序
can't build angular app due to httpClient response data array throwing typescript build issue
你好,我已经离开编码游戏几年了,我正在 Angular 8 上加速(不喜欢它!)我可以 运行 ng serve 一切都很好,但如果我尝试构建我在这里遇到错误
userD() {
// TODO User Angular Service will get to that later.
var aToken = localStorage.getItem('token');
const headers = new HttpHeaders().set("Authorization", "Bearer " + aToken);
this.httpClient.get( 'http://127.0.0.1:8000/api/auth/user', { headers } )
.subscribe((res: any[]) => {
// @ts-ignore
this.users = res.data.result; // it doesn't like the .data.result part in build
console.log(this.users);
});
}
我目前正在使用 //@ts-ignore,不是很理想,但我不知道为什么进入数组时会出现问题,如果我将它作为 res 就可以了。
任何信息都会对帮助我理解这一点很有帮助。谢谢。
注意:编辑
这是 json
我想提取到这个结果对象,然后在 html 中使用 For 循环
{"status":"200", "data": {"result":{"id":3,"name":"patrick lord","email" :"patrick@larvel.io","email_verified_at":null,"phone":"123456789","profilePic":71,"created_at":"2019-09-19 19:43:04 ","updated_at":"2019-09-19 19:43:04","stripe_id":null,"card_brand":null,"card_last_four":null,"trial_ends_at" :null,"gender":"male","Address1":"i don't live here S","Address2":"232","City":"Clearfield","Country":"USA","Zip_Post":"55550","YouTube"}}}
解释
JB 的 一针见血:您收到 TypeScript 错误,因为 any[]
类型 没有 data
属性;根据定义,any[]
期望 任何值 ,唯一的限制是输入必须是 Array
.
类型的对象
但是为什么 build --prod
而不是 serve
中的错误?
您在 ng build --prod
上收到错误而在 ng serve
上收到 not 是因为默认 Angular 环境强制执行 strict
(如“严格遵守打字和语法”)在 --prod
上,但 不会 在本地开发环境中强制执行 strict
。这样一来,在清理代码以供生产使用之前,您可以在本地开发时更轻松地尝试和解决问题,在本地开发时,草率的语法不是问题。我也花了一点时间来解决这个问题,但这是一件好事 (tm) :P
理由
JavaScript 几乎可以让你做任何想做的事情:它不知道 res
会是什么样子,但它假设你知道自己在做什么,如果你说 res
将有一个名为 data
的 属性,它只是随之而来。
如果您有一个小项目,或者如果您是 唯一一个 愿意从事该项目的人,这很好,但是当项目变大,或者如果您有多个开发人员提交代码。 你知道res
有一个data
属性,但是萨曼莎怎么知道的?
输入TypeScript
TypeScript 是 JavaScript...与类型。类型提供给定对象的 shape,因此所有相关人员(包括 TypeScript 转译器)都知道发生了什么。当您说 res: any[]
时,TS 听到的是“对象 res
将成为类型 Array
的 Object
”;然而,我们还没有,告诉 TS 关于数组中的成员项的任何信息,因为它不知道kind 数组 res
将会是,我们唯一可以访问的是 Array
类型本身的泛型方法和属性。
修复
那么,我们需要做什么 而不是 (res: any[])
的 才能使 this.users = res.data.result;
正常工作?
为 ResponseObject 定义接口
我们需要先通过更详细的信息告诉 TS 会发生什么:
export interface ResponseObject {
data: {
result: {};
}
}
现在 TS 知道有一个叫做 ResponseObject
的 Object
有(至少)一个 data
属性,并且 data
属性 是 本身 一个 Object
有(再次,至少)一个 属性 称为 result
.
告诉 TypeScript 期待我们的 ResponseObject
我们可以像这样将它插入我们的订阅调用中:
.subscribe( (res: ResponseObject) => {
this.users = res.data.result; // now it totally DOES like the .data.result part in build --prod!
console.log(this.users);
});
等一下...
您可能会注意到 res
不再是 Array
类型的对象;根据你发布的代码和你说它通过 ng serve
工作的事实,听起来你期待一个单一的 ResponseObject 提供一个 UserObjects 数组作为 data.result
[=138= 上的有效负载];如果是这样,上面的代码示例应该可以正常工作。
然而,如果我们的 .get()
真的 是 返回一个 array ResponseObjects,我们将需要做一些额外的工作。
处理 ResponseObject 数组
首先让我们更改接口声明:
export interface ResponseObject {
status: number; /* It's OK to exclude things we don't need,
but, the status property is going to come in handy when
we eventually want to write a catch statement for cases
when the call returns an error instead of the data we
wanted */
data: {
/* you can also split up your interface declarations to
make them easier to read; this has the added benefit of
allowing us to more easily access the sub-properties of
our payload later on */
result: UserObject; /* we're expecting a single
UserObject per ResponseObject in this scenario,
otherwise we'd use: */
// result: UserObject[];
}
}
export interface UserObject {
/* remember to use the generic type names (lowercase 'string'),
not Primitives (Capitalized 'String') in your interface
declaration, otherwise you'll get more errors */
id: number;
name: string;
email?: string; /* the question mark lets you define a
property that *may* exist, but may not. Useful if your
target API only includes parameters with non-null values
in the ResponseObject */
// ...all the other things you want and think will exist
}
然后我们可以混淆我们的订阅调用:
.subscribe(
// we tell subscribe that we're expecting an array of ResponseObjects
(res: ResponseObject[]) => {
/* users needs to be defined as an array to hold onto
multiple UserObjects; we're clearing it here to make
sure we're only dealing with fresh data and specifying
that it will be an array of type UserObject */
this.users: UserObject = [];
/* the data property isn't a property of the *array*, but
of each array *member-item*, so we need a loop */
res.forEach(
(res_item: ResponseObject) => {
// add the response object data to our users array
this.users.push(res_item.data.result);
});
// now console log should properly show our array of UserObjects!
console.log(this.users);
}
);
n.b., 请不要忘记将其标记为已接受的答案,事实上,满意地回答你的问题。如果有人对您的问题给出了更好或更简洁的答案,您随时可以在事后更改已接受的答案。
干杯!
你好,我已经离开编码游戏几年了,我正在 Angular 8 上加速(不喜欢它!)我可以 运行 ng serve 一切都很好,但如果我尝试构建我在这里遇到错误
userD() {
// TODO User Angular Service will get to that later.
var aToken = localStorage.getItem('token');
const headers = new HttpHeaders().set("Authorization", "Bearer " + aToken);
this.httpClient.get( 'http://127.0.0.1:8000/api/auth/user', { headers } )
.subscribe((res: any[]) => {
// @ts-ignore
this.users = res.data.result; // it doesn't like the .data.result part in build
console.log(this.users);
});
}
我目前正在使用 //@ts-ignore,不是很理想,但我不知道为什么进入数组时会出现问题,如果我将它作为 res 就可以了。
任何信息都会对帮助我理解这一点很有帮助。谢谢。
注意:编辑 这是 json 我想提取到这个结果对象,然后在 html 中使用 For 循环 {"status":"200", "data": {"result":{"id":3,"name":"patrick lord","email" :"patrick@larvel.io","email_verified_at":null,"phone":"123456789","profilePic":71,"created_at":"2019-09-19 19:43:04 ","updated_at":"2019-09-19 19:43:04","stripe_id":null,"card_brand":null,"card_last_four":null,"trial_ends_at" :null,"gender":"male","Address1":"i don't live here S","Address2":"232","City":"Clearfield","Country":"USA","Zip_Post":"55550","YouTube"}}}
解释
JB 的 any[]
类型 没有 data
属性;根据定义,any[]
期望 任何值 ,唯一的限制是输入必须是 Array
.
但是为什么 build --prod
而不是 serve
中的错误?
您在 ng build --prod
上收到错误而在 ng serve
上收到 not 是因为默认 Angular 环境强制执行 strict
(如“严格遵守打字和语法”)在 --prod
上,但 不会 在本地开发环境中强制执行 strict
。这样一来,在清理代码以供生产使用之前,您可以在本地开发时更轻松地尝试和解决问题,在本地开发时,草率的语法不是问题。我也花了一点时间来解决这个问题,但这是一件好事 (tm) :P
理由
JavaScript 几乎可以让你做任何想做的事情:它不知道 res
会是什么样子,但它假设你知道自己在做什么,如果你说 res
将有一个名为 data
的 属性,它只是随之而来。
如果您有一个小项目,或者如果您是 唯一一个 愿意从事该项目的人,这很好,但是当项目变大,或者如果您有多个开发人员提交代码。 你知道res
有一个data
属性,但是萨曼莎怎么知道的?
输入TypeScript
TypeScript 是 JavaScript...与类型。类型提供给定对象的 shape,因此所有相关人员(包括 TypeScript 转译器)都知道发生了什么。当您说 res: any[]
时,TS 听到的是“对象 res
将成为类型 Array
的 Object
”;然而,我们还没有,告诉 TS 关于数组中的成员项的任何信息,因为它不知道kind 数组 res
将会是,我们唯一可以访问的是 Array
类型本身的泛型方法和属性。
修复
那么,我们需要做什么 而不是 (res: any[])
的 才能使 this.users = res.data.result;
正常工作?
为 ResponseObject 定义接口
我们需要先通过更详细的信息告诉 TS 会发生什么:
export interface ResponseObject {
data: {
result: {};
}
}
现在 TS 知道有一个叫做 ResponseObject
的 Object
有(至少)一个 data
属性,并且 data
属性 是 本身 一个 Object
有(再次,至少)一个 属性 称为 result
.
告诉 TypeScript 期待我们的 ResponseObject
我们可以像这样将它插入我们的订阅调用中:
.subscribe( (res: ResponseObject) => {
this.users = res.data.result; // now it totally DOES like the .data.result part in build --prod!
console.log(this.users);
});
等一下...
您可能会注意到 res
不再是 Array
类型的对象;根据你发布的代码和你说它通过 ng serve
工作的事实,听起来你期待一个单一的 ResponseObject 提供一个 UserObjects 数组作为 data.result
[=138= 上的有效负载];如果是这样,上面的代码示例应该可以正常工作。
然而,如果我们的 .get()
真的 是 返回一个 array ResponseObjects,我们将需要做一些额外的工作。
处理 ResponseObject 数组
首先让我们更改接口声明:
export interface ResponseObject {
status: number; /* It's OK to exclude things we don't need,
but, the status property is going to come in handy when
we eventually want to write a catch statement for cases
when the call returns an error instead of the data we
wanted */
data: {
/* you can also split up your interface declarations to
make them easier to read; this has the added benefit of
allowing us to more easily access the sub-properties of
our payload later on */
result: UserObject; /* we're expecting a single
UserObject per ResponseObject in this scenario,
otherwise we'd use: */
// result: UserObject[];
}
}
export interface UserObject {
/* remember to use the generic type names (lowercase 'string'),
not Primitives (Capitalized 'String') in your interface
declaration, otherwise you'll get more errors */
id: number;
name: string;
email?: string; /* the question mark lets you define a
property that *may* exist, but may not. Useful if your
target API only includes parameters with non-null values
in the ResponseObject */
// ...all the other things you want and think will exist
}
然后我们可以混淆我们的订阅调用:
.subscribe(
// we tell subscribe that we're expecting an array of ResponseObjects
(res: ResponseObject[]) => {
/* users needs to be defined as an array to hold onto
multiple UserObjects; we're clearing it here to make
sure we're only dealing with fresh data and specifying
that it will be an array of type UserObject */
this.users: UserObject = [];
/* the data property isn't a property of the *array*, but
of each array *member-item*, so we need a loop */
res.forEach(
(res_item: ResponseObject) => {
// add the response object data to our users array
this.users.push(res_item.data.result);
});
// now console log should properly show our array of UserObjects!
console.log(this.users);
}
);
n.b., 请不要忘记将其标记为已接受的答案,事实上,满意地回答你的问题。如果有人对您的问题给出了更好或更简洁的答案,您随时可以在事后更改已接受的答案。
干杯!