개발새발
jQuery 직접 타이핑하기 본문
타입스크립트에서 타입을 정의하는 일은 종종 단순히 타입 패키지를 사용하는 것으로 충분하지만, 직접 타입을 정의해야 할 상황도 있다. 특히 이미 존재하는 패키지의 타입 정의 파일(.d.ts)을 분석하는 것보다, 타입을 처음부터 직접 만드는 작업은 훨씬 더 어렵다. 이번 글에서는 대표적인 자바스크립트 라이브러리인 jQuery의 타입을 직접 만들어보는 실습을 진행한다.
목표
jQuery 전체를 정밀하게 타이핑하는 것이 아니라, 특정 코드 조각에서 발생하는 에러를 없애는 최소한의 타입 정의를 직접 작성해보는 것이 목표이다. 복잡한 타입 설계보다는, 주어진 코드가 동작하도록 필요한 타입만 작성하는 것이 핵심이다.
준비
jquery라는 폴더 안에 zquery.ts 파일을 생성하고, 아래의 예제 코드를 작성한다.
interface zQuery {}
declare const Z: zQuery;
Z("p").removeClass("myClass noClass").addClass("yourClass");
Z(["p", "t"]).text("hello");
const tag2 = Z("ul li").addClass(function (index) {
return "item-" + index;
});
Z(tag2).html(function () {
console.log(this);
return Z(this).data("name") + "입니다";
});
기존에 $ 변수는 이미 선언되어 있으므로, $ 대신 Z라는 전역 변수를 사용한다. 타입도 zQuery라는 새로운 인터페이스로 선언한다. 또한 tag라는 변수도 다른 곳에서 사용 중일 수 있으므로, tag2로 이름을 변경한다.
현재 zQuery 인터페이스에는 아무런 정의가 없으므로, 대부분의 메서드 사용 부분에서 에러가 발생한다. 이제 이 에러들을 하나씩 없애기 위한 타이핑을 진행하자.
첫 번째 수정: 함수로 선언
먼저 Z(...)의 형태가 함수 호출이므로, zQuery 인터페이스를 함수처럼 선언해야 한다.
interface zQuery {
(tag: string | string[]): zQueryInstance;
}
interface zQueryInstance {}
declare const Z: zQuery;
이렇게 선언하면 Z("p"), Z(["p", "t"]) 같은 호출은 에러가 사라진다. 그러나 여전히 .removeClass() 등의 메서드가 없기 때문에 에러가 발생한다.
두 번째 수정: 메서드 정의
이제 zQueryInstance 인터페이스에 필요한 메서드를 추가한다. 반환 타입은 모두 this로 설정하여 체이닝이 가능하게 만든다.
interface zQueryInstance {
removeClass(param: string): this;
addClass(param: string): this;
text(param: string): this;
html(param: string): this;
data(param: string): this;
}
이제 대부분의 에러는 해결된다. 특히 addClass(...) 호출 이후 tag2의 타입이 zQueryInstance로 추론되어, 이후 Z(tag2)도 사용이 가능해진다.
그러나 여전히 일부 문제는 남아 있다. 예를 들어, addClass()와 html()에 콜백 함수를 넣는 경우, 그리고 Z(this)와 같이 this를 사용하는 경우에 타입 에러가 발생한다.
세 번째 수정: 함수 타입 오버로딩 추가
콜백을 사용하는 메서드는 함수 타입 오버로딩을 추가하여 해결할 수 있다. 또한 Z(...) 함수가 zQueryInstance 인스턴스를 받을 수 있도록 오버로딩을 추가한다.
interface zQuery {
(tag: string | string[]): zQueryInstance;
(tag: zQueryInstance): zQueryInstance;
}
interface zQueryInstance {
removeClass(param: string): this;
addClass(param: string): this;
addClass(callback: (this: zQueryInstance, index: number) => string): this;
text(param: string): this;
html(param: string): this;
html(callback: (this: zQueryInstance, index: number) => string): this;
data(param: string): this;
}
이제 모든 코드가 타입 에러 없이 정상적으로 동작하게 된다. 특히 함수 인자를 받는 메서드에서 this를 명시적으로 설정함으로써, 콜백 내부에서 Z(this) 형태로 사용하는 것도 가능해졌다.
'Typescript' 카테고리의 다른 글
스크립트 파일과 모듈 파일 이해하기 (0) | 2025.05.15 |
---|---|
export = 타입 이해하기 (0) | 2025.05.11 |
jQuery 타입 분석하기 (0) | 2025.05.10 |
tsc와 tsconfigjson (0) | 2025.05.10 |
bind 분석하기 (0) | 2025.05.10 |