타입스크립트에서 동적 객체와 배열을 다루다 보면 예상치 못하게 런타임 에러를 만나는 상황을 겪어볼 수 있습니다. 예를 들어, 배열의 길이를 체크하지 않고 인덱싱을 하거나, 동적 객체의 프로퍼티에 접근할 때 런타임 에러가 발생할 수 있습니다.
이런 문제가 발생하는 근본적인 원인은 추론된 타입이 실제 값과 다른 경우가 있기 때문입니다. 아래와 같이 여러 게시글 중 첫 번째 게시글의 제목을 표시하는 코드가 있다고 가정해보겠습니다.
만약 아무 게시글도 존재하지 않는다면 0번째 요소의 인덱싱 결과는 undefined
이기 때문에 당연하게도 런타임 에러가 발생하게 됩니다. 하지만 타입을 확인해보면 이 코드에서 firstPost
의 타입은 Post
로 추론됩니다.
이런 에러를 방지하기 위해 일반적으로 배열의 길이가 0이 아닌지 확인하는 코드를 추가하게 됩니다. 문제는 위 코드가 런타임 에러를 발생시키는 코드임에도 불구하고 컴파일 단계에서 아무런 에러가 발생하지 않는다는 점입니다. 코드가 안전하게 동작하는지 개발자가 직접 로직을 확인하여 파악해야 한다는 것입니다. 이 문제를 타입스크립트 설정에 아래와 같이 noUncheckedIndexedAccess
옵션을 추가하여 해결할 수 있습니다.
위와 같이 타입스크립트 설정을 바꾼 뒤에는 첫 번째 게시글을 참조했을 때 Post
가 아닌 Post
혹은 undefined
가 반환되므로, 배열이 비어있을 수 있다는 실제 동작을 타입으로 나타낼 수 있게 됩니다. 이제 실수로 배열의 길이를 체크하는 코드를 작성하는 걸 잊었어도 if 문이나 옵셔널 체이닝 등을 통해 안전하게 접근할 수 있도록 타입 레벨에서 보장할 수 있게 된 것입니다. 마찬가지로, 배열 뿐만 아니라 동적 객체도 안전하게 인덱싱 할 수 있게 됩니다.
어떤 맥락에서는 배열이 비어있지 않음을 보장하고 싶을 때가 있습니다. 이럴 때에는 튜플을 활용한 유틸리티 타입으로 배열이 비어있지 않음을 나타낼 수 있습니다.
zod를 사용하고 있다면, nonempty
메소드로 동일한 결과를 얻을 수 있습니다.
NonEmptyArray 타입은 다양한 라이브러리에서 구현되어 있으며, 아래 링크에서 확인할 수 있습니다.