

타입 단언은 TypeScript에서 "이 값의 타입을 나는 이미 알고 있어요"라고 컴파일러에게 말하는 방법이에요. 편리하지만, 편하다는 이유로 남용하면 타입 시스템이 지켜 주던 안전망을 직접 걷어차게 돼요.
타입 단언은 검증이 아니에요
TypeScript의 타입 단언은 런타임 검사처럼 동작하지 않아요. 값을 확인하고 타입을 바꾸는 게 아니라, 컴파일러에게 해석을 요청하는 거예요.
const input = document.getElementById('email') as HTMLInputElement;
input.value = '[email protected]';
이 코드는 input이 실제로 HTMLInputElement라고 믿고 쓰는 거예요. 만약 DOM 구조가 바뀌어서 null이 나오거나 다른 요소가 나오면, TypeScript는 못 막고 런타임에서 터질 수 있어요.
그래서 타입 단언은 "실제로 맞다"를 증명하는 도구가 아니에요. "내가 책임질게"라고 선언하는 도구예요.
써도 되는 순간은 있어요
타입 단언이 유용한 경우는 있어요. 외부 타입 선언이 너무 넓게 잡혀 있거나, DOM 구조를 내가 확실히 알고 있거나, 라이브러리 경계에서 타입 정보를 보강해야 할 때예요.
예를 들면 이런 상황이에요.
- 레이아웃이 고정된 화면에서 특정 DOM 요소를 가져올 때
- 서드파티 라이브러리의 타입이 너무 느슨할 때
- 런타임 검사를 이미 끝냈는데 TypeScript가 그 사실을 모를 때
이런 경우에는 단언이 짧고 실용적이에요. 다만 "이미 검증했다"는 전제가 있어야 해요.
const element = document.querySelector('#submit');
if (!(element instanceof HTMLButtonElement)) return;
element.disabled = true;
이렇게 이미 확인한 뒤라면 단언이 없어도 충분한 경우가 많아요. 단언을 먼저 쓰기보다, 먼저 좁힐 수 있는지 보는 편이 안전해요.
피해야 할 순간
입력값이 외부에서 들어오는데 단언부터 거는 건 위험해요. API 응답, 사용자 입력, JSON.parse() 결과처럼 실제 값이 달라질 수 있는 데이터는 타입 단언보다 런타임 검증이 먼저예요.
const data = JSON.parse(text) as User;
이 코드는 편해 보여도, text가 User가 아니어도 컴파일은 통과해요. 이런 경우에는 unknown으로 받고, 속성을 검사하거나 타입 가드를 써야 해요.
타입 단언이 자주 필요하다면 대개 모델이 덜 정확하다는 신호예요. 단언으로 덮기보다 입력 경계를 다시 봐야 해요.
더 안전한 대안이 있어요
타입 단언이 자주 필요하다면 대개 모델이 덜 정확하다는 신호예요. 이럴 때는 다음 순서를 먼저 봐야 해요.
- 타입 가드로 런타임 검사를 추가해요.
unknown을 써서 검증 전 값을 안전하게 다뤄요.- 구조를 나눠서 애초에 단언이 필요 없는 형태로 바꿔요.
as보다 더 안전한 선택이 있는지 먼저 봐야 해요. as는 마지막 수단에 가깝고, ! 같은 비슷한 escape hatch도 같은 기준으로 다뤄야 해요.
정리
- 타입 단언은 "이 값이 이 타입이라고 믿어도 된다"는 컴파일러 힌트예요.
- DOM처럼 구조가 고정된 곳이나 이미 검증한 경계에서는 유용해요.
- 외부 입력이나 불확실한 데이터에 먼저 쓰면 안전망이 약해져요.


