网站搜索

javascript - Angular 9 在 http 响应后的类型转换问题


我有一个组件,它在初始化时从 API 获取学生信息。这是我 组件版本1 上的 onIniti 代码

ngOnInit(): void {
    if(!this.student) {
      this.studentsService.getStudentDetail(this.id).subscribe(
        (response: Student) => {
          this.student = response;
        },
        error => console.log(error)
      )
    }
  }

这是我 student-service-version1 内的函数

getStudentDetail(id: number): Observable<Student> {
    return this.httpClient.get<Student>(`${this.studentsUrl}${id}/`, this.baseService.httpOptions);
  }

一切运行正常。现在,仅出于教学目的(我刚接触 JavaScript/TypeScript),我想重构我的服务,以便使用一个单一的 get 函数,当不带参数调用时返回学生列表,而在传入特定 ID 时返回学生的详细信息。这是 students-service-version2

getStudents(id?: number): Observable<Student[]> {
    if(id)
      return this.httpClient.get<Student[]>(`${this.studentsUrl}${id}/`, this.baseService.httpOptions);
    else
      return this.httpClient.get<Student[]>(this.studentsUrl, this.baseService.httpOptions);
  }

鉴于我的函数签名表明它返回一个学生数组的可观察对象,在我的组件中我需要某种类型转换,从 Student[] 到 Student。我的做法如下:component-version2

ngOnInit(): void {
    if(!this.student) {
      this.studentsService.getStudents(this.id).subscribe(
        (response: Student[]) => {
          this.student = response[0] as Student;
        },
        error => console.log(error)
      )
    }
  }

这不起作用,所以在初始化之后,student 变量仍然是未定义的。我不明白为什么,对我来说一切看起来都正确(虽然这种重构不是一个好主意。再说一次,我只是想理解背后的错误)我也尝试了 this.student=response.pop() as Student; 结果相同,依然不工作。

答案#1

ngOnInit(): void {
if(!this.student) {
  this.studentsService.getStudents(this.id).subscribe(
    (response: Student[]) => {
      // Hope, this.student will have type as any, public student: any
      this.student = !this.id ? response[0] as Student : response as Student[];
    },
    error => console.log(error)
  )
}

}

始终尝试返回一个数组以避免冲突。在上面的代码中,三元运算符会完成你的工作。因为,如果你有一个 id,这意味着你正在请求特定学生的信息,否则你是在请求所有学生记录。

答案#2

你的服务现在应该在对你大喊,因为你在对编译器撒谎……你的返回类型不是 Observable<Student[]>,而是 Observable<Student[] | Student>……我完全不同意一个函数同时用于单个获取和列表获取的原则,但你可以在单个情况下强制它为列表……

return this.httpClient.get<Student>(`${this.studentsUrl}${id}/`, this.baseService.httpOptions).pipe(
  map(student => [student])
);

如果某样东西不是数组,没有类型转换会把它转成数组。如果你想要这样,你需要明确地把它变成数组。