TypeScript에서는 시스템이 추론 및 분석한 타입 내용을 우리가 원하는 대로 얼마든지 바꿀 수 있다. 이때 “타입 표명(type assertion)”이라 불리는 메커니즘이 사용된다.
TypeScript의 타입 표명은 프로그래머가 컴파일러에게 내가 너보다 타입에 더 잘 알고 있고, 나의 주장에 대해 의심하지 말라고 하는 것 과 같다.
타입 표명은 JavaScript 코드를 TypeScript로 포팅할 때 많이 쓰인다. 예를 들어 다음과 같은 형태를 보자.
var foo = {};
foo.bar = 123; // 오류: 속성 'bar'가 '{}'에 존재하지 않음
foo.bas = 'hello'; // 오류: 속성 'bar'가 '{}'에 존재하지 않음
위 코드는 에러를 발생시키는데 그 이유는 foo가 {}, 즉 속성이 하나도 없는 빈 객체로 타입 추론이 되었기 때문이다. 그러므로 bar나 bas 같은 속성을 foo에 추가할 수 없는 것이다. 이런 문제는 as Foo라는 타입 표명을 사용해서 간단히 해결할 수 있다.
interface Foo {
bar: number;
bas: string;
}
var foo = {} as Foo; // as 키워드를 통해 '{}'를 Foo로 캐스팅
foo.bar = 123;
foo.bas = 'hello';
원래 타입 표명으로 추가되었던 구문은 <foo>와 같은 꺽쇠였다. 아래에 나와 있듯이
var foo: any;
var bar = <string> foo; // 이제 bar의 타입은 "문자열"이다.
그러나 꺽쇠 스타일(<foo>)의 구문을 사용하면 JSX에서 문법적으로 모호한 경우가 발생한다.
var foo = <string>bar;
</string>
적지 않은 경우에 타입 표명을 사용하면 레거시 코드를 마이그레이션할 때 쉽게 넘어갈 수 있지만, 개발자가 깜빡해서 넣어줘야할 타입을 넣어주지 않는 실수를 범해버릴 수 있다. 또한 임시 변수를 추가해야하는 경우도 생기기 때문에 아래와 같이 명시적으로 안전하게 사용하자.
interface Foo {
bar: number;
bas: string;
}
var foo: Foo = {
// 컴파일러가 Foo의 속성에 대해 자동완성을 지원할 것이다.
};
타입 표명(Type Assertion) | TypeScript Deep Dive
📘 타입 추론 / 타입 호환 / 타입 단언 / 타입 가드 💯 총정리