책/이펙티브 타입스크립트
[타입선언, @types 50] 오버로딩/조건부 타입
atmosg
2022. 8. 1. 15:33
1. 타입스크립트 오버로딩
TS에선 타입 수준에서만 이라면 함수 오버로딩이 가능하다. 예를 들어, 아래처럼 두 개의 함수를 동일한 이름, 다른 타입의 매개변수로 선언할 수 있다. 생긴 게 혼란하지만 어차피 타입 정보만 제공할 뿐이므로 런타임에선 제거된다.
- function double(x: string): string;
- function double(x: number): number;
2. 타입 정보 추가해보기
function double (x) { return x+x }
만약 위처럼 생겼고 string이나 number를 받는 double 함수를 만든다고 해보자. 단, number 타입을 넣으면 반환 타입이 number이고 string이면 반환 타입이 string으로 깔끔하게 나오길 바란다(유니온 타입 말고) 이 경우 어떻게 타입 정보를 만들 수 있을까?
1) 유니온 타입
애석하게도 유니온 타입으로 만들면 반환 타입을 딱 number나 string으로 구분해주지 못한다.
function double(x: number|string): number|string;
function double(x: any) { return x+x }
const num = double(12); // 반환타입이 string | number
const str = double('x'); // 반환타입이 string | number
2) 오버로딩
위에서 언급했듯 타입 수준에서만 이라면 오버로딩이 가능하므로 여러 개 선언해두는 방법도 있다. 그러나 이는 중복의 발생뿐만 아니라, 이 함수를 유니온 타입으로 호출할 수도 없게 된다.
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
// 어.. 저는 유니온 타입으로 호출하고싶은데
// double 이분이 싫다시네요;;
function f(x: number | string) {
return double(x)
// ~ 'string | number'형식의 인수는
// 'string' 형식의 매개변수에 할당 못함
// 'number' 형식의 매개변수에 할당 못함
}
3) 조건부 타입
if 문으로 조건별 분기를 하듯 타입도 조건별로 분기를 할 수 있다. 물론 if문을 그대로 쓸 수 있다는 소리는 아니고 삼항 연산자로 조건부 타입을 지정할 수 있다.
function double<T extends number | string> (x: T): T extends string ? string : number;
function double(x: any) {
return x+x;
}
const num = double(1) // 반환타입 number
const str = double('x') // 반환타입 string
// 이렇게 유니온 타입으로 호출도 가능하다
function f(x: string|number) {
return double(x)
}
3. 결론
사실 오버로딩으로 타입을 작성할 일이 그리 많겠냐만은, 만약 필요한 경우 조건부 타입이 가능한지 확인해보자