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)[] 으로 잡힐거고 실제로도 그렇게 잡히니 타입이 제대로 잡혀있다.
그럼 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)[]으로 잡힌다.
위 사진을 통해서 실제로도 타입이 잘못잡혀있는걸 확인할수 있다.
해결방법
위와 같은 상황에서 타입을 제대로 받는 방법에는 총 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)[];
'Programming > Typescript' 카테고리의 다른 글
[Typescript] typescript에서 enum을 반복하는 방법 (0) | 2022.11.08 |
---|---|
[Typescript] typescript에서 express의 request를 확장해서 사용하는 방법 (0) | 2022.07.29 |
[Typescript] Typescript에서 class가 다중상속을 지원하지 않는 이유 (다이아몬드 문제) (0) | 2022.07.24 |
[Typescript] typescript에서 type과 interface의 속성을 재정의하는 방법 (typescript Overriding) (1) | 2022.07.13 |
[Mongoose] mongoose를 typescript와 사용하는 방법 (0) | 2022.07.11 |