解释
JB 的 comment 正中要害:您遇到了 TypeScript 错误,因为 any[] 类型没有 data 属性;根据定义,any[] 期待 anything,唯一的限制是输入必须是 Array 类型的对象。
但是为什么build --prod 中的错误而不是serve 中的错误?
您在ng build --prod 上收到错误,而在ng serve 上出现not 是因为默认 Angular 环境在 @ 上强制执行 strict(如“严格遵守键入和语法”) 987654332@,但不在本地开发环境中强制执行strict。这样一来,在清理代码以供生产使用之前,您可以在本地开发时更轻松地解决问题,其中草率的语法不是问题。我也花了一点时间来解决这个问题,但这是一件好事(tm):P
理由
JavaScript 可以让你做任何你想做的事:它不知道res 会是什么样子,但它假设你知道你在做什么,如果你说res 将有一个属性称为data,它只是随它滚动。
如果您有一个小项目,或者如果您是唯一人会一直从事该项目,那就太好了,但是当项目变得更大时,它开始变得棘手,或者如果您有多个开发人员提交代码。 你知道res有一个data属性,但是Samantha怎么知道呢?
输入TypeScript
TypeScript 是 JavaScript...带有类型。类型提供给定对象的 shape,因此所有相关人员(包括 TypeScript 转译器)都知道发生了什么。当你说 res: any[] 时,TS 听到的是“对象 res 将成为 Object 类型的 Array”;然而,我们还没有告诉 TS 关于数组中的成员项within 的任何信息,因为它不知道 种类 是什么数组res 将是,我们唯一可以访问的是Array 类型本身的泛型方法和属性。
修复
那么,我们需要做什么而不是 (res: any[]) 来使 this.users = res.data.result; 工作?
为 ResponseObject 定义一个接口
我们需要先告诉 TS 会发生什么,并提供更多细节:
export interface ResponseObject {
data: {
result: {};
}
}
现在 TS 知道有一个名为 ResponseObject 的 ResponseObject 具有(至少)一个 data 属性,而 data 属性本身是一个具有 (再次,至少)一个名为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 工作的事实,听起来您期待一个响应对象,它提供一组用户对象作为data.result 属性上的有效负载;如果是这样,上面的代码示例应该可以正常工作。
但是,如果我们的.get() 真的是返回一个数组 ResponseObjects,我们将需要做一些额外的工作。
处理 ResponseObjects 数组
让我们先修改一下接口声明:
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., 如果它确实令人满意地回答了您的问题,请不要忘记将其标记为已接受的答案。如果有人对您的问题提出了更好或更简洁的答案,您可以随时更改已接受的答案。
干杯!