Devlog.
게시일

TypeScript Array filter 타입 좁히기

cover
date
Nov 8, 2023
slug
typescript-array-filter-타입-좁히기
status
Published
tags
TypeScript
summary
타입 가드로 Array filter 타입 추론하기
type
Post

TypeScript에서 배열의 .filter() 메서드는 타입을 필터링하지 않는다.

TypeScript는 코드 구조와 주석을 기반으로 타입을 결정하는 정적 타입 시스템이다. 따라서 필터링 조건이 더 구체적인 서브타입을 제안하더라도 결과 배열의 타입을 자동으로 좁히지 않는다.
필터링된 배열의 타입을 명시적으로 좁히려면 타입 가드 함수를 사용해야 한다.
 
다음 예제를 확인해보자.
interface Bird { type: "bird"; flyingSpeed: number; } interface Fish { type: "fish"; swimmingSpeed: number; } type Animal = Bird | Fish; const animals: Animal[] = [ { type: "bird", flyingSpeed: 10 }, { type: "fish", swimmingSpeed: 15 }, ]; const isBirdWithoutTypePredicate = (animal: Animal) => animal.type === "bird"; const isBird = (animal: Animal): animal is Bird => animal.type === "bird"; const birds1 = animals.filter(isBirdWithoutTypePredicate); const birds2 = animals.filter(isBird); const birds3 = animals.filter((animal) => isBird(animal));
TS Playground
  • birds1의 경우 타입 가드 함수를 사용하지 않아 Bird[]가 아닌 Animal[]로 추론되는 것을 확인할 수 있다.
  • birds2의 경우 타입 가드 함수를 사용하여 Bird[]로 추론되는 것을 확인할 수 있다.
  • birds3의 경우 화살표 함수 내에서 타입 가드 함수를 사용하지만, 화살표 함수 자체는 타입 가드 함수가 아니므로 Animal[]로 추론되는 것을 확인할 수 있다.

.filter(Boolean)의 경우

이 글을 작성하게 된 계기이다. 자바스크립트에서 배열에 있는 nullish한 값을 필터링하기 위해 .filter(Boolean)를 자주 사용했는데, 타입스크립트에서 위에서 말했던 타입 문제로 인해 당황한 경험이 있다.
다음과 같이 유틸리티 타입인 NonNullable을 사용하여 타입 가드 함수를 작성하면 문제 없이 타입을 좁힐 수 있다.
const array = ["item1", "item2", null, undefined]; const isNonNullable = <T extends unknown>(v: T): v is NonNullable<T> => Boolean(v); const filteredArray = array.filter(isNonNullable);
TS Playground