TypeScript에서 함수와 메서드를 설계하다 보면 “이 함수가 어떤 객체에서 호출되느냐”, “인자에 따라 반환 타입이 달라져야 하는 상황”을 자주 만나게 됩니다.
이때 중요한 개념이 바로 this 타입과 함수 오버로드(Function Overload)입니다. 이 두 가지를 잘 활용하면 메서드 체이닝, 빌더 패턴, 다형적인 API를 타입 안정성 있게 설계할 수 있습니다.
this 타입이란?
TypeScript에서 this 타입은 “해당 메서드를 호출한 객체 자신의 타입”을 의미합니다.
class Counter {
value = 0;
increment() {
this.value++;
return this;
}
}
여기서 this의 타입은 Counter입니다. 즉, 반환 타입이 자동으로 Counter로 추론됩니다.
this 타입의 가장 큰 장점 — 메서드 체이닝
this 타입을 사용하면 상속 구조에서도 타입이 깨지지 않는 체이닝이 가능합니다.
class Base {
log() {
console.log("base");
return this;
}
}
class Child extends Base {
childMethod() {
return this;
}
}
const c = new Child();
c.log().childMethod(); // 정상
만약 반환 타입을 Base로 명시했다면 childMethod() 호출은 불가능했을 것입니다.
함수에서 this 타입 명시하기
함수에서도 첫 번째 가짜 인자로 this 타입을 명시할 수 있습니다.
type User = {
name: string;
};
function greet(this: User) {
return `Hello ${this.name}`;
}
이 함수는 반드시 User 객체를 this로 바인딩해서 호출해야 합니다.
const user = { name: "Alice" };
greet.call(user); // OK
greet(); // ❌ 오류
콜백, 이벤트 핸들러, call/apply/bind 사용 시 매우 유용한 패턴입니다.
this 타입과 noImplicitThis
noImplicitThis 옵션이 켜져 있으면 this 타입이 명확하지 않은 경우 컴파일 에러가 발생합니다.
function foo() {
console.log(this); // ❌ this: any
}
이 문제를 해결하는 가장 좋은 방법이 바로 명시적인 this 타입 선언입니다.
함수 오버로드란?
함수 오버로드는 하나의 함수에 여러 호출 시그니처를 정의하는 방식입니다.
function format(value: string): string;
function format(value: number): string;
function format(value: string | number) {
return value.toString();
}
외부에서는 서로 다른 함수처럼 보이지만, 구현은 하나로 유지됩니다.
오버로드가 필요한 이유
유니온 타입만으로는 다음과 같은 문제가 발생합니다.
function bad(value: string | number) {
return value.toFixed(2); // ❌ string에는 없음
}
오버로드를 사용하면 입력 타입에 따라 반환 타입을 정확히 표현할 수 있습니다.
반환 타입이 달라지는 오버로드
function parse(value: string): number;
function parse(value: number): string;
function parse(value: string | number) {
return typeof value === "string"
? Number(value)
: value.toString();
}
const a = parse("10"); // number
const b = parse(10); // string
이 패턴은 API 파서, 유틸리티 함수에서 매우 자주 사용됩니다.
this 타입 + 함수 오버로드 조합
두 개념을 함께 사용하면 더욱 강력한 API를 만들 수 있습니다.
class Builder {
value = "";
set(value: string): this;
set(value: number): this;
set(value: string | number) {
this.value = String(value);
return this;
}
}
new Builder()
.set("hello")
.set(123);
입력 타입에 따른 오버로드, this 반환으로 체이닝 유지 → 실무에서 가장 이상적인 빌더 패턴
실무에서 자주 쓰이는 패턴
- Fluent API / Builder 패턴
- DOM / 이벤트 핸들러 유틸리티
- 설정 객체 체이닝
- 다형적 유틸 함수
- 라이브러리 Public API 설계
특히 외부에 노출되는 API에서는 this 타입 + 오버로드 조합이 사실상 표준입니다.
주의사항
- 오버로드 시그니처와 구현 시그니처 불일치 주의
- 구현 시그니처는 가장 넓은 타입으로 작성
- 오버로드가 과도하면 가독성 저하
- 단순 분기는 제네릭이나 유니온이 더 나을 수도 있음
this 타입과 함수 오버로드는 TypeScript에서 호출 맥락과 다형성을 안전하게 표현하는 중요한 도구입니다.
- this 타입 → 호출 객체의 타입 유지, 체이닝 안전성
- 함수 오버로드 → 입력/출력 타입 정확한 표현
- 두 개를 조합하면 강력한 Public API 설계 가능
'개발 > Typescript' 카테고리의 다른 글
| [TYPESCRIPT] DOM 타입 정의 이해하기 — TypeScript로 안전한 브라우저 코드 작성 (0) | 2025.12.23 |
|---|---|
| [TYPESCRIPT] 함수형 프로그래밍과 TypeScript - 불변성과 타입으로 만드는 안정적인 코드 (0) | 2025.12.22 |
| [TYPESCRIPT] Index Signature와 동적 객체 타입 - 키가 정해지지 않은 객체를 안전하게 다루는 방법 (0) | 2025.12.20 |
| [TYPESCRIPT] Readonly와 const assertion - 불변성을 타입으로 보장하는 방법 (0) | 2025.12.19 |
| [TYPESCRIPT] Discriminated Union 패턴으로 안전한 분기 처리 - 타입으로 보장하는 조건 분기 (0) | 2025.12.18 |
