any에는 타입 안정성이 없다
따라서 코드의 혼란이 가중된다.
let age: number
age = '12'
// Type 'string' is not assignable to type 'number'.
age = '12' as any // OK
any는 함수 시그니처를 무시해 버린다
함수 시그니처란 함수 작성 시 명시되어 있는 입력과 출력의 타입을 의미한다. any 타입을 사용하면 이런 약속을 어길 수 있다.
function calculateAge(birthDate: Date): number {
// ...
}
let birthDate: any = '1990-01-19'
calculateAge(birthDate) // OK
위의 코드에서도 Date 타입인 birthDate에 string이 들어갔다면 어떤 문제가 발생할지 예측할 수 없다.
any 타입에는 언어 서비스가 적용되지 않는다
any 타입을 사용하면 자동완성 기능의 도움을 받을 수 없다.
let person: any = { first: 'George', last: 'Washington' }
person. // 자동완성으로 first와 last가 나오는 게 인지상정
Rename Symbol을 통해 속성 값을 통째로 변경할수도 없다.
interface Person {
first: string
last: string
}
const formatName = (p: Person) => `${p.first} ${p.last}`
const formatNameAny = (p: any) => `${p.first} ${p.last}`
// => formatName의 first 심볼을 Rename Symbol을 통해 firstName으로 변경
interface Person {
firstName: string
last: string
}
const formatName = (p: Person) => `${p.firstName} ${p.last}`
const formatNameAny = (p: any) => `${p.first} ${p.last}` // 변경되지 않음
any 타입은 코드 리팩터링 때 버그를 감춘다
interface ComponentProps {
onSelectItem: (item: any) => void
}
function renderSelector(props: ComponentProps) { /** ... */ }
let selectedId: number = 0
function handleSelectItem(item: any) {
selectedId = item.id
}
renderSelector({ onSelectItem: handleSelectItem })
위에서 onSelectItem에 아이템 객체를 통째로 넘겨주지 않고 필요한 부분만 전달하도록 리팩토링 해보자.
interface ComponentProps {
onSelectItem: (id: number) => void
}