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로 지정하여 함수 내에서 변경 불가능하게 만들어볼 수 있다.
아래 제네릭 제약 조건을 보면 배열의 요소 타입이던 any
에 Readonly
유틸리티 타입을 사용했다.
<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.
})
};