Item17 - 변경 관련된 오류 방지를 위해 readonly 사용하기
function arraySum(arr: number[]) {
let sum = 0,
num;
while ((num = arr.pop()) !== undefined) {
sum += num;
}
return sum;
}
function printTriangles(n: number) {
const nums = [];
for (let i = 0; i < n; i++) {
nums.push(i);
console.log(arraySum(nums));
}
}
printTriangles(5)
>0
>1
>2
>3
>4
해당코드에서 원하는 값은 이렇습니다 1,3,6,10 하지만 전혀 다른값들이 출력되어지고있습니다.
오류의 원인은 이렇습니다.
1.printTriangles 함수에서 첫 루프 0을 push 한후 arraySum을 호출합니다.
2.arraySum은 숫자배열을 매개변수로 전달받고 첫번째 루프에선 배열에 [0] 이 들어 있을 것 입니다.
3.[0] 만 들어가있는 상태에서 pop메서드를 사용하니 다시 빈배열이 될것이고 두번째 루프엔 빈배열에 1만 push되어 [1] 될것입니다.
4.따라서 요소들이 서로 합쳐지지않는 오류가 발생하게됩니다.
자바스크립트(타입스크립트포함)에서는 명시적으로 언급하지 않는한, 함수가 매개변수를 변경하지 않는다고 가정합니다.
하지만 이는 타입체크에 문제를 일으킬수 있습니다.
따라서 명시적인 방법을 사용하는것이 컴파일러와 개발자 모두에게 좋습니다.
오류의 범위를 좁히기위해 readonly 접근 제어자를 사용해보겠습니다.
function arraySum(arr: readonly number[]) {
let sum = 0,
num
while ((num = arr.pop()) !== undefined) {
// ~~~ 'readonly number[]' 형식에는 'pop' 속성이 없습니다.
sum += num
}
return sum
}
readonly number[] 은 number[] 타입과 차이점이 있습니다.
- 배열의 요소를 읽을 수 있지만, 쓸 수는 없다
- length를 읽을 수 있지만, 바꿀 수는 없다.
- 배열을 변경하는 pop을 비롯한 다른 메서드를 호출할 수 없다.
number[] 는 readonly number[] 보다 기능이 많기 때문에, readonly number[]의 서브타입이 된다. 따라서 변경 가능한 배열을 readonly 배열에 할당할 수 있다. 하지만 그 반대는 불가능합니다.
const a:number[] = [1,2,3];
const b:readonly number[] = a;
const c:number[] = b;
// ~ 'readonly number[] 타입은 readonly 이므로 변경가능한 number[] 타입에 할당될 수 없습니다.
매개변수를 readonly 로 선언하면 여러가지 일이 생깁니다
- 타입스크립트는 매개변수가 함수 내에서 변경이 일어나는지 체크 합니다.
- 호출하는 쪽에서 함수가 매개변수를 변경하지 않는다는 보장을 받게 됩니다.
- 호출하는 쪽에서 함수에 readonly 배열을 매개변수로 넣을수 있습니다.
앞선 예제의 arraySum 의 코드를 고쳐서 값이 정상적으로 나오도록 해보겠습니다. 배열을 변경하지 않으면 됩니다.
function arraySum(arr:readonly number[]){
let sum = 0;
for(const num of arr){
sum+=num;
}
return sum;
}
>> 0 1 3 6 10 정상적으로 결과값이 나온다.
만약 함수가 매개변수를 변경하지 않는다면, readonly로 선언해야합니다. 더 넓은 타입으로 호출할 수 있고, 의도치 않은 변경은 방지 됩니다.
요약.
- 함수가 매개변수를 수정하지 않는다면 readonly로 선언하는 것이 좋습니다. 인터페이스를 명확하게하며,매개변수가 변경되는것을 방지하기 때문입니다.
- readonly 는 얕게 동작 한다는것을 명심해야 한다.
.
'Typescript' 카테고리의 다른 글
Effective Typescript - 아이템19 (0) | 2023.04.12 |
---|---|
Effective Typescript - 아이템18 (0) | 2023.04.12 |
Effective Typescript - 아이템16 (0) | 2023.04.11 |
Effective Typescript - 아이템15 (0) | 2023.04.11 |
Effective Typescript - 타입 연산과 제네릭 사용으로 반복 줄이기 (0) | 2023.04.11 |