Angular 9 проблема с приведением типов после ответа http - PullRequest
1 голос
/ 05 мая 2020

У меня есть компонент, который извлекает информацию о студенте из API после его инициализации. Это код onIniti на моей cmponent-version1

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);
  }

Все отлично работает. Теперь, только для didacti c цели (я новичок в javascript / typescript), я хотел бы реорганизовать свою службу, чтобы использовать единственную функцию get , которая возвращает список студентов при вызове без параметра и вместо этого возвращать подробную информацию о студенте при вызове с указанным c id. Это student-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);
  }

Учитывая, что в сигнатуре моей функции указано, что она возвращает наблюдаемый массив студентов, в моем компоненте мне нужно своего рода приведение типов из Студент [] - Студент . Вот как я это делаю: версия-компонента2

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

Это не работает, поэтому после инициализации student var остается неопределенным. Я не понимаю, почему, мне все кажется правильным (хотя этот рефакторинг - не лучшая идея. Опять же, я просто хочу понять причину ошибки). Я также пробую this.student = response.pop() as Student; Тот же результат, не работает.

Ответы [ 3 ]

5 голосов
/ 06 мая 2020
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)
  )
}

}

Всегда старайтесь вернуть массив, чтобы избежать конфликтов. В приведенном выше коде вашу работу выполнит тернарный оператор. Например, если у вас есть идентификатор, который означает, что вы запрашиваете информацию о конкретном ученике, в противном случае вы запрашиваете все записи ученика.

3 голосов
/ 05 мая 2020

ваша служба должна кричать на вас прямо сейчас, потому что вы лжете компилятору ... ваш тип возврата не Observable<Student[]> его Observable<Student[] | Student> ... я не согласен с принципом одной функции для single и list вообще получается, но вы можете заставить его быть списком в единственном случае ...

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

никакое приведение типов не преобразует что-то в массив, если это не массив. вам нужно явно сделать его массивом, если вы этого хотите.

1 голос
/ 05 мая 2020

Перегрузите подпись вашего метода следующим образом:

class StudentService {
  get(id: number) | Observable<Student>;
  get(): Observable<Student[]>;
  get(id: number | undefined): Observable<Student[]> | Observable<Student> {
    if(id !== undefined)
      return this.httpClient.get<Student[]>(`${this.studentsUrl}${id}/`, this.baseService.httpOptions);
    else
      return this.httpClient.get<Student>(this.studentsUrl, this.baseService.httpOptions);
  }
} 

Обратите внимание, как метод был переименован, чтобы иметь смысл в любом случае, как тип возвращаемого значения соотносится с наличием параметра id , и как проверка была изменена, чтобы учесть возможность 0 в качестве действительного идентификатора.

...