공부
[이펙티브TS] 오버로딩보다 조건부 타입 사용하기(아이템 50)
jaeeedev
2023. 8. 12. 21:13
function double(x) {
return x + x;
}
double 함수에는 string이나 number가 들어올 수 있다.
function double(x: number | string): number | string;
function double(x: any) {
return x + x;
}
const num = double(12); // number|string
const str = double("x"); // number|string
이런 결과 나옴. 타입이 아직 포괄적이다...
제네릭을 사용하면?
function double<T extends number | string>(x: T): T;
function double(x: any) {
return x + x;
}
const num = double(12); // 12
const str = double("x"); // "x"
타입이 과하게 구체적이다. 그리고 str은 "xx"를 반환하기 때문에 의미도 모호하다.
여러개로 타입을 분리하면?
function double(x: number): number;
function double(x: string): string;
function double(x: any) {
return x + x;
}
const num = double(12); // number
const str = double("x"); // string
잘 되는것 같지만... 유니온 타입
에서 문제 발생함
function f(x: number | string) {
return double(x);
} // Argument of type 'string | number' is not assignable to parameter of type 'string'. 대충 이런 오류 나옴
타입스크립트는 오버로딩 타입 중 일치하는 타입을 찾을 때 까지 검색하는데 마지막까지 string|number 타입과 일치하는 타입이 없어서 오류 발생 (string이 string|number보다 정확한 타입이니까 할당 불가능)
조건부 타입 사용하기
function double<T extends number | string>(
x: T
): T extends string ? string : number;
function double(x: any) {
return x + x;
}
자바스크립트의 삼항 연산자처럼 사용하면 됨.
const num = double(12); // number
const str = double("x"); // string
앞선 제네릭 예제와 유사하지만 반환 타입이 더 정교하다.
function (x: string | number) {
return double(x);
}
유니온 타입일때도 문제없이 동작한다.
T가 number|string일 때 조건부 타입의 해석 과정
(number | string) extends string ? string: number
->
(number extends string ? string : number) | (string extends string ? string : number)
->
number | string
오버로딩 타입이 작성은 쉽지만 조건부 타입이 더 정확하다. 오버로딩 타입을 사용 중이라면 조건부 타입으로 개선을 고려해 볼 수 있다.