Я не совсем уверен, где вы столкнулись с проблемой. Если вы пытаетесь разрешить карту в ValidationErrors внутри валидатора, вам нужно будет проверить тип. В этом примере я возвращаю ошибку с именем "apiError", чтобы отличить ее от ошибки "принято", но я не уверен, как вы решите обработать этот случай в своем приложении.
Я предполагаю, что ErrorResponse
содержит поле error
, а SuccessResponse
содержит поле data
.
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return this.isUsernameTaken(control.value as string)
.pipe(
map(response => {
if ('error' in response) { // response is ErrorResponse
return { apiError: response.error };
}
return response.data ? { taken: true } : null;
})
);
};
Если вы создаете фактические экземпляры класса, используя new ErrorResponse()
и new SuccessResponse()
вы можете использовать intanceof
вместо проверки полей с помощью оператора in
. например, if (response instanceof ErrorResponse)
.
В качестве альтернативы , вы можете передать ошибку обратно валидатору и обработать ответ в другом catchError
. Я предпочитаю этот способ, потому что в ответе от API нет условного logi c.
Validator
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return this.isUsernameTaken(control.value as string)
.pipe(
map(response => response.data ? { taken: true } : null),
catchError((err: ErrorResponse) => of({ apiError: err.error }))
);
};
}
ApiService
isUsernameTaken(username: string): Observable<SuccessResponse> {
return this.http.get('/backend/account/checkUnique', { params: { username } })
.pipe(
map(response => response as SuccessResponse), // maps the api response to SuccessResponse
catchError(this.handleError) // maps the error to ErrorResponse
);
}
handleError(error: HttpErrorResponse): Observable<never> {
let errorResponse: ErrorResponse;
// specific payload of ErrorResponse based on error.status
return throwError(errorResponse);
}