제네릭과 readonly를 이용하여 함수 안에서 불변성을 지니는 배열 운영하기

nearworld·2023년 5월 31일
0

typescript

목록 보기
27/28
function takeArray<T extends readonly any[]>(
  list: T[number] extends {id: number} ? T : never
) {
  // 아래 코드는 에러가 발생한다. 이유는 push 메서드가 지원되지 않기때문이다.
  list.push(); // T에 readonly 제약조건이 걸려있으므로 배열이 제약조건이라 하더라도
  //push 메서드가 코드 자동완성 목록에 아예 없다.
  // pop 메서드도 마찬가지로 지원되지 않는다.
  
  // map같이 list의 불변성을 위배하지 않는 메서드들은 사용가능하다.
  list.map(); // 정상 작동
}
// 변경가능한 people 배열이 있다.
const people = [
  {id: 1, name: 'kim'},
  {id: 2, name: 'park'}
];
// 변경 가능한 people 배열을 takeArray 함수에 던져준다.
takeArray<typeof people>(people);

takeArray 함수 안으로 들어간 people 배열은 readonly로 인식되고 변경 불가능해진다. 이렇게 함수 내부에서 인자에 대해 readonly를 걸어주면 매번 데이터를 만들때마다 readonly 타입을 지정해줄 필요가 없다. 효율적인 함수 설계라고 생각이 든다.

이번에는 배열의 요소인 객체도 readonly로 지정하여 함수 내에서 변경 불가능하게 만들어볼 수 있다.

아래 제네릭 제약 조건을 보면 배열의 요소 타입이던 anyReadonly 유틸리티 타입을 사용했다.
<T extends readonly Readonly<any>[]>

function takeArray<T extends readonly Readonly<any>[]>(
  list: T[number] extends {id: number} ? T : never
) {
  list.map(item => {
   item.name = 100; // type error: Index Signature Readonly<any> only permits reading. 
  })
};
profile
깃허브: https://github.com/nearworld

0개의 댓글