데코레이터로 메서드 반환 재정의
17909 단어 typescripttutorialbeginners
자, 이제 API 응답을 수정하는 데 어떻게 사용할 수 있는지 살펴보겠습니다. 이 문서의 목적을 위해 우리는 Star Wars api 및 Angular 을 사용할 것입니다. 이미 데코레이터 더미를 자체적으로 사용하고 있으므로...
id로 api에서 영웅을 요청하는 서비스를 추가하고 응답을 한 눈에 보고 인터페이스로 변환해 보겠습니다. 다음과 같습니다.
// src/app/models/hero.model.ts
interface Hero {
name: string;
height: string;
mass: string;
hair_color: string;
skin_color: string;
eye_color: string;
birth_year: string;
gender: string;
homeworld: string;
films: string[];
species: string[];
vehicles: string[];
starships: string[];
created: string;
edited: string;
url: string;
}
따라서 서비스는 다음과 같이 표시됩니다.
// src/app/services/star-wars-api/star-wars-api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Hero } from 'src/app/models/hero.model';
@Injectable({
providedIn: 'root',
})
export class StarWarsApiService {
private readonly api = 'https://swapi.dev/api';
constructor(private http: HttpClient) {}
public getHero(id: number): Observable<Hero> {
const url = `${this.api}/people/${id}`;
return this.http.get<Hero>(url);
}
}
좋아 보이지만 어떤 이유로
Date
및 created
필드에 edited
유형을 갖고 싶다고 상상해 봅시다.개체를 순회하고 문자열을 날짜로 변환할 수 있는 함수를 빌드해 보겠습니다.
// src/app/utils/convert-string-to-date-recursively.util.ts
export function convertStringToDateRecursively<T>(
obj: any,
checkDate: (s: string) => boolean
): T {
for (const k in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, k)) {
continue;
}
const value = obj[k];
if (Array.isArray(value)) {
value.map((el) => convertStringToDateRecursively(el, checkDate));
continue;
}
if (typeof value === 'string' && checkDate(value)) {
obj[k] = new Date(value) as any;
continue;
}
if (typeof value === 'object') {
obj[k] = convertStringToDateRecursively(value, checkDate);
}
}
return obj;
}
따라서 우리는 모든 개체를 수락하고 해당 필드를 반복하고
string
에서 checkDate
까지 날짜 문자열로 확인된 모든 Date
를 변환합니다. 문자열이 날짜인지 확인하는 별도의 기능을 제공하면 관심사를 더 잘 분리할 수 있으므로 변환기는 변환만 처리합니다.이 함수는
Hero
를 created
및 edited
를 Date
유형으로 갖는 다른 인터페이스로 변환하기 위해 파이프에서 사용할 수 있지만 위험하므로 데코레이터를 사용하여 즉시 변환을 수행합니다. Hero
인터페이스에서 해당 필드의 유형을 직접 변경하기만 하면 됩니다. 엔터프라이즈 응용 프로그램에는 좋은 생각이 아니지만 애완 동물 프로젝트 또는 데코레이터와의 장난에는 적합합니다.메서드 데코레이터는 기본적으로
target
, propertyKey
및 descriptor
를 인수로 받아들이고 이들을 사용하여 무엇이든 수행할 수 있는 함수이므로 기존 클래스 메서드의 동작을 재정의하는 데 사용할 수 있습니다. 우리의 목적을 위해 문자열 날짜를 Observable
유형으로 변환하기 위해 원래 메서드에서 반환된 map
와 우리가 만든 convertStringToDateRecursively
함수로 파이프할 것입니다. 문자열이 날짜인지 확인하기 위해 Date
패키지의 함수를 사용할 것입니다. 이 함수는 단순히 문자열이 유효한 ISO-8601 날짜인지 확인하고 부울을 반환하므로 우리의 필요에 맞습니다.// src/app/decorators/map-strings-to-dates.decorator.ts
import { map, Observable } from 'rxjs';
import { isValidISODateString } from 'iso-datestring-validator';
import { convertStringToDateRecursively } from '../utils/convert-string-to-date-recursively.util';
export function mapStringsToDates(
target: unknown,
propertyKey: string,
descriptor: PropertyDescriptor
): void {
const originalMethod = descriptor.value;
descriptor.value = function (...args: unknown[]) {
return (<Observable<unknown>>originalMethod.apply(this, args)).pipe(
map((r) => convertStringToDateRecursively(r, isValidISODateString))
);
};
}
아주 간단하게, 남은 것은 방법을 장식하는 것입니다.
// src/app/services/star-wars-api/star-wars-api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Hero } from 'src/app/models/hero.model';
import { mapStringsToDates } from 'src/app/decorators/map-strings-to-dates.decorator';
@Injectable({
providedIn: 'root',
})
export class StarWarsApiService {
private readonly api = 'https://swapi.dev/api';
constructor(private http: HttpClient) {}
@mapStringsToDates
public getHero(id: number): Observable<Hero> {
const url = `${this.api}/people/${id}`;
return this.http.get<Hero>(url);
}
}
이제
iso-datestring-validator
인터페이스를 업데이트하고 Hero
및 Date
필드의 유형으로 created
를 입력할 수 있습니다.그게 전부입니다. 이제 불을 가지고 놀 수 있습니다 :D
추신 repo with code :)
Reference
이 문제에 관하여(데코레이터로 메서드 반환 재정의), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/bwca/override-method-return-with-a-decorator-1bii텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)