[Typescript] filter 제네릭 분석

Bewell·2024년 3월 9일
0

filter의 타입에 대해 분석해보자

//	lib.es5.d.ts

interface Array<T> {
    filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
    filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[];
}

const filtered = [1,2,3,4,5].filter(value => value % 2)

filter는 두가지 타입이 정의되어 있는데, 첫번째 타입을 기준으로 분석해보자



filtered함수에 Array<T>Array<number>로 들어가 Tnumber가 되고, S extendes number로 함수의 리턴값에 S[] -> number[] 가 추론된다

반면에 문자열과 숫자가 섞인 로직을 분석해보자

const result = [1,'2',3,'4',5].filter((value) => typeof value === 'string');

여기서 result의 타입은 무엇이 나올까?
string[] 으로 나올 것 같지만, (string | number)[] 가 나온다. 왜일까?
그 이유는 filter 타입에서 확인할 수 있다

T(string | number)[] 값이 들어가고, S extends T -> S extends (string | number)[] 로 추론하기 때문에, 함수의 리턴값(결과값)이 (string | number)[] 로 나올 수 밖에 없다

그럼 더 정확한 타입인 string[] 으로 추론하고 싶다면 어떻게 하면 될까?
filter의 정의된 타입을 보면 value is S 를 찾을 수 있다

is 관련 문서

/**
 * Step1 - 콜백함수를 새로 선언
 */
const cb = (value) => typeof value === 'string'
const result = [1,'2',3,'4',5].filter(cb);


/**
 * Step2 - value is string을 통해 타입가드 적용
 */
const cb = (value): value is string => typeof value === 'string'
const result = [1,'2',3,'4',5].filter(cb);

value is string 를 사용하여 Type Guard(타입가드)로 변수 result 타입을 string[]으로 한정된 범위로 추론할 수 있다

0개의 댓글