[Typescript] map, filter 함수 만들기

Bewell·2024년 3월 13일
post-thumbnail

map을 만들어보자

interface Arr<T> {
    map():void
}

const a: Arr<number> = [1,2,3,4]
const b = a.map(v => v+1)

처음 map을 간단한 형태로 선언한다.



변수 b 가 void가 아니기 때문에 map의 파라미터에 들어갈 callback 값을 정의해준다

interface Arr<T> {
    map(callback: (v: T) => void):void	//	<--변경
}

const a: Arr<number> = [1,2,3,4]
const b = a.map(v => v+1)



여기서 변수 b의 타입은 void로 나오는데 map의 리턴값을 정의해주자

interface Arr<T> {
    map<S>(callback: (v: T) => S): S[]	//	<--변경
}



실제 lib.es5.d.ts에서의 map의 타입과 비교해보자

    map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
    map<S>(callback: (v: T) => S): S[]	

두번째, 세번째 파라미터를 제외하면 callback fn의 타입은 정확히 일치한다






filter는 타입추론이 제대로 안된다?

const a = [1,2,3,4,'5'].filter((v) => typeof v === 'string')

여기서 변수 a는 (string | number)[]로 타입이 추론된다. 당연히 예상컨데 string[]으로 나와야할 것 같지만 아니다.

이걸 좀 더 정확하게 타이핑하려면 어떻게 해야할까?
filter에 선언된 타입을 살펴 보자

//	lib.es5.d.ts

/**
 * Returns the elements of an array that meet the condition specified in a callback function.
 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
 * @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.
 */
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
/**
 * Returns the elements of an array that meet the condition specified in a callback function.
 * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
 * @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.
 */
filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[];

첫번째 predicate callback을 보면 value is S 로 타입가드가 되어 있다. 이를 통해 해결할 수 있다

const a = [1,2,3,4,'5'].filter((v): v is string => typeof v === 'string')

0개의 댓글