TypeScript 팁: 조건부 유형을 사용하여 오버로드를 리팩터링합니다.
12440 단어 typescriptjavascriptwebdev
소개
며칠 전에 코드를 리팩토링하다가 다음과 같은 것을 발견했습니다.
interface IRawUser {
first_name: string
email: string,
id: number,
}
interface User {
name: string,
email: string
print: () => void
}
declare function userFactory(rawUser: IRawUser): User;
function mapRawToUserObject(rawShow: IRawUser[]): User[];
function mapRawToUserObject(rawShow: IRawUser): User;
function mapRawToUserObject(rawShow: IRawUser | IRawUser[]): User | User[] {
if (rawShow instanceof Array) {
return rawShow.map((raw) => userFactory(raw));
}
return userFactory(rawShow);
}
함수
mapRawToUserObject
는 오버로드를 사용하여 다음을 표현합니다. IRawUser[]
의 배열로 호출하면 User[]
의 배열을 반환하고 단일IRawUser
로 호출하면 단일User
을 반환합니다. ) .너무 복잡하지는 않지만 메서드 정의를 리팩토링할 수 있는 좋은 기회인 것 같습니다.
조건부 유형 생성.
메서드가 받는 입력 유형을 결정해야 합니다.
살펴봐야 할 가능한 입력은
IRawUser
및 IRawUser[]
입니다.type MapRawResult<T extends IRawUser | IRawUser[]> = any;
그런 다음 조건부 논리를 추가합니다.
type MapRawResult<T extends IRawUser | IRawUser[]> = T extends IRawUser ? User : User[]
In plain words: If
T
is assignable toIRawUser
returnUser
otherwise returnUser[]
우리의 방법에 조건부 유형을 적용합니다.
지금 우리의 방법은 다음과 같습니다.
function mapRawToUserObject(rawShow: IRawUser[]): User[];
function mapRawToUserObject(rawShow: IRawUser): User;
function mapRawToUserObject(rawShow: IRawUser | IRawUser[]): User | User[] {
// implementation
}
이제 오버로드를 제거하고 일반 매개변수(
T extends IRawUser | IRawUser[]
)를 추가하고 반환 유형을 최근에 만든 것으로 바꿀 수 있습니다.type MapRawResult<T extends IRawUser | IRawUser[]> = T extends IRawUser ? User : User[]
function mapRawToUserObject<T extends IRawUser | IRawUser[]>(rawShow: T): MapRawResult<T> {
// implementation
}
이 시점에서 typescript는 우리가 반환하는 값의 유형에 대해 불평할 것입니다.
컴파일러는 우리가 반환하는 값의 유형을 유추할 수 없습니다. 이에 대한 해결책은 키워드
as
를 사용하여 예상되는 유형을 명시적으로 표현하는 것입니다.최종 방법은 다음과 같습니다.
function mapRawToUserObject<T extends IRawUser | IRawUser[]>(rawShow: T): MapRawResult<T> {
if (rawShow instanceof Array) {
return rawShow.map((raw) => userFactory(raw)) as MapRawResult<T>
}
return userFactory(rawShow) as MapRawResult<T>
}
결론
일부 값으로 시도하면 메서드가 오버로드를 사용하지 않고 이전과 동일하게 동작하는 방식을 볼 수 있습니다.
보너스로
IRawUser | IRawUser[]
에 대한 유형 별칭을 사용하고 코드를 더 깔끔하게 만들 수 있습니다.type MapRawArg = IRawUser | IRawUser[];
type MapRawResult<T extends MapRawArg> = T extends IRawUser ? User : User[];
function mapRawToUserObject<T extends MapRawArg>(rawShow: T): MapRawResult<T> {
// ...
}
추가 자료
Reference
이 문제에 관하여(TypeScript 팁: 조건부 유형을 사용하여 오버로드를 리팩터링합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/andersonjoseph/typescript-tip-using-conditional-types-to-refactor-overloads-3e60텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)