- 타입스크립트에서 일반적으로 변수의 타입은 변수를 선언할 때 결정
- 그 후에 정제될 수 있지만(null인지 체크), 새로운 값이 추가되도록 확장할 수 없음
- any 타입과 관련해서는 예외인 경우가 존재
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[]
}
return out; // Type is number[]
}
- out의 타입이 처음에는 any타입 배열인 []로 초기화 ⇒ 마지막에는 number[]로 추론
- number값이 push되는 순간부터 타입이 number[]로 진화
- 타입의 진화는 타입 좁히기와 다름
- 배열에 다양한 타입의 요소를 넣으면 배열 타입이 확장되며 진화
const result = []; // Type is any[]
result.push('a');
result // Type is string[]
result.push(1);
result // Type is (string | 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 블록 안에서 변수를 할당하는 경우)
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(**타입을 any타입으로 지정하였을 때, 오류가 발생할지 안할지에 대한 옵션)**가 설정된 상태에서 변수의 타입이 암시적 any인 경우 일어남
- 명시적으로 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 상태인 변수에 어떠한 할당도 하지 않고 사용하려고 하면 암시적 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);
}
return out;
}
- any 타입의 진화는 암시적 any타입에 어떤 값을 할당할 때만 발생
- 어떤 변수가 암시적 any상태일 때 값을 읽으려고 하면 오류가 발생
- 암시적 any타입은 함수 호출을 거쳐도 진화하지 않음
function makeSquares(start: number, limit: number) {
const out = [];
// ~~~ Variable 'out' implicitly has type 'any[]' in some locations
range(start, limit).forEach(i => {
out.push(i * i);// **forEach안의 화살표 함수는 추론에 영향을 주지 않음**
});
return out;
// ~~~ Variable 'out' implicitly has an 'any[]' type
}
- 루프로 순회하는 대신, 배열의 map과 filter를 사용해 단일 구문으로 배열을 생성하여 any 전체를 진화시키는 방법을 사용할 수 있음
- 스코프 관점에서 생각하면 이해하기 편한듯? ⇒ 상위에서는 하위의 정보를 알 수 없으니까!
- any가 진화하는 방식은 일반적인 변수가 추론되는 원리와 동일
- 타입을 안전하게 지키기 위해서는 암시적 any를 진화시키는 방식보다 명시적 타입 구문을 사용하는 것이 더 좋은 결과
요약
- 일반적인 타입들은 정제되긴만 하는 반면, 암시적 any와 any[] 타입은 진화 할 수 있다. 이러한 동작이 발생하는 코드를 인지하고 이해할 수 있어야 함
- any를 진화시키는 방식보다 명시적 타입 구문을 사용하는 것이 안전한 타입을 유지하는 방법