반응형

typescript사용시 filter를 통해 undefined나 null을 배열에서 제거 할 때 타입이 제대로 잡히지 않는 현상이 일어났다. 해당일이 일어난 원인과 해결방법을 알아보자.

 

환경

typescript: 4.4.3

node.js: v16.15.0

 

문제 상황

아래와 같은 test 배열이 있다고 가정을 하고 값과 타입을 추론해보자.

const test = ['test', 'test2', 'test3', undefined, 'test4', 'test5', undefined];
console.log(test); // ['test', 'test2', 'test3', undefined, 'test4', 'test5', undefined]

당연히 typescript에서 추론한 test의 타입은 (string | undefined)[] 으로 잡힐거고 실제로도 그렇게 잡히니 타입이 제대로 잡혀있다.

test의 타입

그럼 filter 메서드를 사용해서 test 배열에 있는 undefined를 제거하면 어떻게 될까?

const test2 = test.filter(str => str !== undefined);
console.log(test2); // ['test', 'test2', 'test3', 'test4', 'test5']

 

test2변수에는 test에서 undefined를 제거한 배열만 담았다 그럼 test2의 타입은 string

[]이 되어야 한다.

하지만 typescript에서 자동으로 추론한 타입은 test1과 동일한 (string | undefined)[]으로 잡힌다.

test2의 타입

위 사진을 통해서 실제로도 타입이 잘못잡혀있는걸 확인할수 있다.

 

 

해결방법

위와 같은 상황에서 타입을 제대로 받는 방법에는 총 2가지 방법이 있다.

1. type predicates를 사용한 방법

// solution1: string[]
const solution1 = test.filter((str): str is string => str !== undefined);

 

2. 타입 단언을 사용한 방법

// solution2: string[]
const solution2 = test.filter((str) => str !== undefined) as string[];

위의 문제 상황은 해결이 된다.

 

조심할 점

위 두가지 방식중 하나를 택해서 사용할 수 있고, 타입을 확인하면 제대로 잡혀있는걸 확인할 수 있다. 하지만 조심해서 사용해야 한다.

만약 test에 다른값이 들어가 있는 경우 (number나 null 같은) 타입이 제대로 잡히지 않는 문제가 발생할 수 있다.

예를 들어 test3가 있다고 가정해보자.

 

// const test3: (string | null | undefined)[]
const test3 = ['test', 'test2', 'test3', undefined, 'test4', 'test5', undefined, null];

 

test3에서 typescript가 추론한 타입은 (string | null | undefined)[] 이다. 하지만 위 2개의 방식대로 해결하면 string[]이 나온다.

 

// const fail1: string[]
// const fail2: string[]
const fail1 = test3.filter((str): str is string => str !== undefined);
const fail2 = test3.filter((str) => str !== undefined) as string[];

 

이럴때 개발자는 무슨 타입이 나오는지 또는 다른 타입이 들어가지 않는지 확인해줘야 하며 다른 타입이 들어간다면 그에 맞게 타입를 수정해주어야 한다 신중하게 사용해야 한다.

 

위 예시에서는 아래처럼 사용할 수 있다.

// const solution1: (string | null)[]
// const solution2: (string | null)[]
const solution1 = test3.filter((str): str is (string | null) => str !== undefined);
const solution2 = test3.filter((str) => str !== undefined) as (string | null)[];

 

반응형
얼은펭귄