Item 17 변경 관련된 오류 방지를 위해 readonly 사용하기

함수가 매개변수를 수정하지 않는다면 readonly로 선언하자

function arraySum(arr: readonly number[]) {
  let sum = 0; num;
  while ((num = arr.pop()) !== undefined) {
                 // ~~~ 'readonly number[]' 형식에 'pop' 속성이 없습니다.
    sum += num
  }
  return num
}

readonly number[]number[]와 달리...

  • 배열의 요소를 읽을 수는 있지만 쓸 수는 없다.

  • length를 읽을 수는 있지만 바꿀 수는 없다.

  • 배열을 변경하는 pop을 비롯한 다른 메서드를 호출할 수 없다.

매개변수를 readonly로 선언하면 다음과 같은 일이 일어난다.

  • TS는 매개변수가 함수 내에서 변경이 일어나는지 체크한다.

  • 호출하는 쪽에서는 함수가 매개변수를 변경하지 않는다는 보장을 받게 된다.

  • 호출하는 쪽에서 함수에 readonly 배열을 매개변수로 넣을 수도 있다.

readonly는 얕게 동작한다

예를 들어 객체의 readonly 배열이 있다면, 그 객체 자체는 readonly가 아니다.

const dates: readonly Date[] = [new Date()]
dates.push(new Date())
   // ~~~~ 'readonly Date[]' 형식에 'push' 속성이 없습니다.
dates[0].setFullYear(2037)
  • readonly 타입이 기본으로 지원되지 않지만 제너릭을 만들면 깊은 readonly를 사용할 수 있다.

  • 하지만 제너릭 구현은 까다로우니 라이브러리를 사용하는 방법이 있다. (e.g., ts-essentials)

Summary

  • 만약 함수가 매개변수를 수정하지 않는다면 readonly로 선언하자.

    • readonly 매개변수는 인터페이스를 명확하게 하며, 매개변수가 변경되는 것을 방지한다.

  • readonly를 사용하면 변경하면서 발생하는 오류를 방지할 수 있고, 변경이 발생하는 코드도 쉽게 찾을 수 있다.

  • constreadonly의 차이를 이해하자.

  • readonly얕게 동작한다는 것을 이해하자.

Last updated