이펙티브 타입스크립트 (댄 밴더캄 지음) 를 읽고 정리
📍요약
✅암시적 any와 any[] 타입은 진화할 수 있다
- 명시적 any : 진화 없이 계속 any
- any 타입의 진화 : 중간에 값이 할당되거나, 배열에 원소가 추가되면 타입이 변경되는 것
✅any 진화는 타입 안정성에 좋지는 않다
- 중간에 실수로 타입이 오염될 수 있음
- 명시적 타입 구문이 바람직하다
📍변수의 타입이 any인 경우, 다른 타입으로 확장될 수 있다
일반적으로 변수의 타입이 선언 시에 결정된다. 그리고 한번 정해지면 새로운 값이 추가되지 않는다
- 그러나 any의 경우, 예외가 존재한다
예시) 일정 범위의 숫자를 배열에 담아 리턴하는 함수
- out 의 타입이 변경된다 (any -> number[])
function range(start: number, limit: number) {
const out = []; // Type is any[]
for (let i = start; i < limit; i++) {
out.push(i); // Type of out is any[]
// any 타입의 진화는 값을 할당하거나, 배열에 요소를 넣은 후에만 발생하므로
// 아직은 계속 any[]
}
return out; // Type is number[]
}
✅조건문에서는 분기에 따라 타입이 변화한다
let val; // Type is any
if (Math.random() < 0.5) {
val = /hello/;
val // Type is RegExp
} else {
val = 12;
val // Type is number
}
val // Type is number | RegExp
✅변수 선언 시에 null 을 할당해도 일단 any가 배정된다.
- 또한 try/catch 문의 경우에도 조건문처럼 any 진화가 발생한다
function somethingDangerous() {}
let val = null; // Type is any
try {
somethingDangerous();
val = 12;
val // Type is number
} catch (e) {
console.warn('alas!');
}
val // Type is number | null
✅any 타입의 진화는 noImplicitAny=true 일 때만 발생하며, 명시적으로 any를 설정하면 타입이 그대로 유지된다
let val: any; // Type is any
if (Math.random() < 0.5) {
val = /hello/;
val // Type is any
} else {
val = 12;
val // Type is any
}
val // Type is any
✅암시적 any (implicitly any) 상태인 변수를 할당 전에 곧장 사용하려고 하면, Implicitly Any 에러 발생
- 함수를 호출해도 Implicitly Any 에러 발생
- 암시적 any 상태일 때는 바로 사용할 수 없다
function range(start: number, limit: number) {
const out = [];
// ~~~ Variable 'out' implicitly has type 'any[]' in some
// locations where its type cannot be determined
if (start === limit) {
return out;
// ~~~ Variable 'out' implicitly has an 'any[]' type
}
for (let i = start; i < limit; i++) {
out.push(i); // 아직 any[]
}
return out;
}