Typescript와 forEach

정길웅·2023년 8월 12일

제로쵸 : 타입을 사용하는것 뿐 아니라 타입을 만들줄도 알아야합니다!

타입을 단순하게 지정하고 사용하는 것이 아니라 타입을 만든다라는 개념이 좀 생소했다. 그래서 이번 제로쵸 강의가 크게 도움이 되었다. 오늘은 forEach를 통해서 타입을 생성하는 개념을 제로쵸 강의의 흐름대로 정리해보았다.

1단계 : 사용할 코드의 타입을 거꾸로 파악한다

const a:Arr = [1,2,3]
a.forEach((item) => {
    console.log(item);
})

이런 코드에서 Arr의 타입을 지정해보도록 하자. 거꾸로 파악한다는 뜻은 forEach에서 사용하는 타입을 거꾸로 추론하는 것이다. 저 식을 예로 들자면 forEach는 void함수이고 안에 들어가는 배열은 콜백함수로 이루어져있다. 고로, 이런식으로 추론할 수 있다.

interface Arr {
	forEach(callback: (item:number)=> void):void
}

2단계 : 코드를 범용성 좋게 수정해본다(제네릭 사용)

이제 forEach에서 string과 number 케이스 두 가지를 선택적으로 적용하는 방법에 대해 알아보도록 하자. 여기에서 선택적이라는 표현으로 우리는 제네릭을 사용해야 한다는 사실을 떠올려야 한다. 아래의 예시에서 a는 number, b는 string을 사용하는 함수이다

interface Arr {
    forEach(callback: (item: string | number) => void): void;
}

const a:Arr = [1,2,3];
a.forEach((item) => {
    console.log(item);
    item.toFixed(1); //number에서만 가능
})

const b:Arr = ['1','2','3'];
b.forEach((item) => {
    console.log(item);
    item.charAt(1); //string에서만 가능
})

위 예시에서 a와 b를 둘 다 잡기 위해 string|number 타입을 사용하였으나 오히려 두 코드에서 동시에 오류가 발생하였다. 이 해결책은 사용하는 쪽에서 타입을 지정해주는 제네릭을 사용하는 것이다.

interface Solution<T> {
    forEach(callback: (item: T) => void): void;
}

const c:Solution<number> = [1,2,3]
c.forEach((item) => {
    console.log(item);
    item.toFixed(1); //number에서만 가능
})

const d:Solution<string> = ['1','2','3'];
d.forEach((item) => {
    console.log(item);
    item.charAt(1); //string에서만 가능
})

위 코드에서는 Solution이라는 제네릭 메소드를 사용하여 item의 타입에 따라 가변적으로 바뀌게 생성하였다. 그 결과로 c와 d의 타입에서 안에 속한 함수를 자유롭게 사용할 수 있게 되었다.

profile
사람들과 소통하는 FE 개발자입니다

0개의 댓글