해당 게시글은
강의 사이트, 인프런에서 이정환님이 진행하시는
'한 입 크기로 잘라먹는 타입스크립트' 를
들어보며 블로그를 작성하려고 합니다.
다음 게시글 내용은 해당 강의에 핸드북의 내용으로
출처는 다음과 같습니다.
https://ts.winterlood.com/7250edd7-a3fd-4662-b756-f11f927c73f2
타입스크립트를 소개합니다 - 타입스크립트 개론
한 입 크기로 잘라먹는 타입스크립트
ts.winterlood.com
section7/chapter2.ts 에서 실습을 진행했습니다.
이전에 배운 제네릭을 이용해
자바스크립트의 배열 메서드 Map, ForEach 를 직접 구현하고
타입을 정의해보겠습니다.
Map 메서드 타입 정의하기
자바스크립트의 배열 메서드 Map 은 다음과 같이
원본 배열의 각 요소에 콜백함수를 수행하고
반환된 값들을 모아 새로운 배열로 만들어 반환합니다.
const arr = [1, 2, 3];
const newArr = arr.map((it) => it * 2);
// [2, 4, 6]
https://reactjs.winterlood.com/fc0a951e-41cd-4cc5-8f47-7507965bbe41#70f057d3a5e24e8090674ed49fb0ad58
7. 배열과 메서드 - 2. 자바스크립트 실전
인사이트 도서 <한 입 크기로 잘라먹는 리액트> 를 미리 만나보세요
reactjs.winterlood.com
map 메서드를 직접 함수로 만들고 타입도 정의하겠습니다.
먼저 제네릭 함수가 아닌 일반적인 함수로 만듭니다.
function map(arr: unknown[], callback: (item: unknown) => unknown): unknown[] {}
메서드를 적용할 배열을 매개변수 arr 로 받고,
콜백 함수를 매개변수 callback 으로 받습니다.
map 메서드는 모든 타입의 배열에 적용할 수 있기 때문에
arr 의 타입은 unknown[ ] 으로 정의합니다.
callback 의 타입은 배열 요소 하나를 매개변수로 받아
특정 값을 반환하는 함수로 정의합니다.
함수 타입 표현식을 이용했습니다.
마지막으로 map 메서드의 반환값의 타입은 배열 타입으로 정의합니다.
다음으로는 이 함수에 타입 변수를 선언해 제네릭 함수로 만듭니다.
function map<T>(arr: T[], callback: (item: T) => T): T[] {}
모든 unknown 타입을 변수 T 로 대체합니다.
다음으로는 함수 내부를 구현합니다.
function map<T>(arr: T[], callback: (item: T) => T): T[] {
let result = [];
for (let i = 0; i < arr.length; i++) {
result.push(callback(arr[i]));
}
return result;
}
1차적으로 map 함수를 만들고, 타입 정의도 마쳤습니다.
이제 함수를 호출합니다.
const arr = [1, 2, 3];
function map<T>(arr: T[], callback: (item: T) => T): T[] {
(...)
}
map(arr, (it) => it * 2);
// number[] 타입의 배열을 반환
// 결과 : [2, 4, 6]
잘 동작하는 것 같습니다.
매개변수 arr 에 number[ ] 타입의 배열을 제공하니
타입변수 T 가 number 로 추론되고
그 결과 map 함수의 반환값 타입도 number[ ] 가 되었습니다.
그런데 문제가 한 가지 있습니다.
함수 호출을 다음과 같이 수정하면 오류가 발생합니다.
const arr = [1, 2, 3];
function map<T>(arr: T[], callback: (item: T) => T): T[] {
(...)
}
map(arr, (it) => it.toString()); // ❌
콜백함수가 모든 배열 요소를 String 타입으로 변환하도록 수정했습니다.
이러면 오류가 발생합니다.
첫 번째 인수로 arr 을 전달했을 때
타입 변수 T 에는 number 타입이 할당되었기 때문에
콜백 함수의 반환값 타입도 number 타입이 되어야 하기 때문입니다.
그런데 map 메서드는 이렇게 원본 배열 타입과
다른 타입의 배열로도 변환할 수 있어야 합니다.
따라서 타입 변수를 하나 더 추가해 다음과 같이 수정합니다.
const arr = [1, 2, 3];
function map<T, U>(arr: T[], callback: (item: T) => U): U[] {
(...)
}
map(arr, (it) => it.toString());
// string[] 타입의 배열을 반환
// 결과 : ["1", "2", "3"]
원본 배열의 타입과 새롭게 반환하는 타입을
다르게 설정해 주었습니다.
그 결과 호출문의 오류가 사라지고 잘 작동합니다.
ForEach 메서드 타입 정의하기
다음으로는 forEach 메서드도 직접 구현하고
타입도 함께 정의해보겠습니다.
forEach 메서드는 다음과 같이
배열의 모든 요소에 콜백함수를 한 번씩 수행해주는 메서드입니다.
const arr2 = [1, 2, 3];
arr2.forEach((it) => console.log(it));
// 출력 : 1, 2, 3
https://reactjs.winterlood.com/fc0a951e-41cd-4cc5-8f47-7507965bbe41#f8b1bbedf6cc4c96932b9536a9c2f02e
7. 배열과 메서드 - 2. 자바스크립트 실전
인사이트 도서 <한 입 크기로 잘라먹는 리액트> 를 미리 만나보세요
reactjs.winterlood.com
ForEach 메서드는 Map 메서드보다 훨씬 만들기도 쉽고 타입 정의도 간단합니다.
function forEach<T>(arr: T[], callback: (item: T) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i]);
}
}
Map 과 동일하게 2개의 매개변수를 받습니다.
첫 번째 매개변수 arr 에는 순회 대상 배열을 제공받고
두 번째 매개변수 callback 에는 모든 배열 요소에 수행할 함수를 제공받습니다.
이때 아까 Map 메서드의 타입 정의와는 달리
forEach 메서드는 반환값이 없는 메서드이므로
콜백 함수의 반환값 타입을 void 로 정의합니다.
'TypeScript > 한 입 크기로 잘라먹는 타입스크립트' 카테고리의 다른 글
[제네릭] 제네릭 클래스 (0) | 2023.07.19 |
---|---|
[제네릭] 제네릭 인터페이스, 제네릭 타입 별칭 (0) | 2023.07.19 |
[제네릭] 타입 변수 응용하기 (0) | 2023.07.16 |
[제너릭] 제너릭 소개 (0) | 2023.07.15 |
[클래스] 인터페이스와 클래스 (0) | 2023.07.15 |