💡 기존에 alias용도로 as를 사용하기 시작하다가 조금은 정리가 좀 필요할 것 같아서 정리하려는 찰나에 is 키워드도 알게되면서 덩달아 정리해보려고 한다.
const instanceOfToDo = (object: any): object is IToDo => {
return (
object.constructor === Object &&
"id" in object &&
"text" in object &&
typeof (object as IToDo).id === "number" &&
typeof (object as IToDo).text === "string"
);
};
as 키워드는 컴파일러가 객체를 추론하는 유형이 아닌 다른 유형으로 객체를 고려하도록 컴파일러에 지시하는 TypeScript의 유형 어설션입니다.
위 인용은 docs 문서를 번역한것이다. 요약하자면 ‘컴파일’ 단계에서 타입 검사를 할 때 타입스크립트가 감지하지 못하는 애매한 타입 요소들을 직접 명시해주는 키워드라고 볼 수 있다. 예를 들어 아래와 같은 코드가 있다고 하자.
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
이 코드에서 as HTMLCanvasElement 부분이 없다고 가정한다면, 타입스크립트는 그저 myCanvas가 여러 HTMLElement 중 어느 하나의 HTMLElement만을 가질 것이란 사실 밖에 알지 못한다. 이러한 경우에 as HTMLCanvasElement를 적어줌으로써 myCanvas가 HTMLCanvasElement를 가진다는 것을 알게 되며 에러의 확률을 줄일 수 있게 된다.
위 코드는 as 키워드를 사용하지 않고도 표현할 수 있는데, tsx 파일 내에 있다고 가정하고 아래와 같이 쓸 수 있다.
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
한 가지 특징은 as 키워드(type assertion)은 오직 컴파일 단계에서만 실행되며 런타임 단계에서는 삭제된 채로 실행된다. 컴파일 단계에서 제대로 넘어갔다면 런타임 단계에서의 에러 발생은 일어나지 않는다는 말이다.
function isString(test: any): test is string{
return typeof test === "string";
}
function example(foo: any) {
if (isString(foo)) {
console.log("it is a string" + foo);
console.log(foo.length); // string function
}
}
example("hello world");
위 isString() 함수를 살펴보면 return 문의 값이 true일 때, test is string이란 type predicate 구문이 있기 때문에 타입스크립트는 이 함수를 호출한 범위 내에서 isString()의 결과 타입을 string으로 좁힌다.
그러니까 isString() 함수를 거쳐서 return 값이 true라면, type predicate에 적은 말 그대로 ‘함수가 호출된 범위 내에선 test를 string 타입으로 보라’ 는 것이다. 위 as 키워드와 마찬가지로 is 키워드 역시 컴파일 단계에서만 사용되며 런타임 단계에서는 순수한 js 파일과 동일하게 동작한다.
아래의 코드는 컴파일 그리고 런타임 단계에서 에러가 발생하는데, 그 이유는 타입스크립트가 foo의 타입을 string으로 좁혀놓은 상태에서 toExponential() 함수가 string 메소드에 속하지 않는다는 에러를 체크하기 때문이다.
function example(foo: any) {
if (isString(foo)) {
console.log("it is a string" + foo);
console.log(foo.length);
console.log(foo.toExponential(2)); // Error! 이미 string으로 좁혀놨는데 Number의 메소드를 시도하고 있다.
}
}
as키워드는 Type Assertion(타입 단언)으로, 컴파일 단계에서 타입스크립트가 잘못 혹은 보수적으로 타입을 추론하는 경우 개발자가 수동으로 컴파일러에게 특정 변수에 대한 타입 힌트를 주는 것이다.
is키워드는 Type Guard(타입 가드)로,as가 특정 변수 하나에 국한된 것이라면is키워드는 한정된 범위 내의 모든 변수에 대해서 일괄적으로 적용할 수 있는 키워드이다.