프론트엔드/TypeScript

[TypeScript] 타입 단언 (Type Assertion)

종종 실제 타입이 컴파일러가 추론한 타입보다 구체적인 상황이 발생합니다.

이러한 상황에서 타입 단언을 쓰면 컴파일러에게 특정 타입을 단언할 수 있습니다.

 


타입 단언 (Type Assertion)

종종 컴파일러보다 개발자가 타입을 더 잘 알 때가 있습니다.

주로 데이터의 실제 타입이 컴파일러가 추론한 타입보다 구체적인 상황이 됩니다.

타입 단언은 컴파일러에게 특정 타입을 명시적으로 단언하는 개념입니다.

 

타입 단언은 런타임에 영향을 미치지 않습니다.

즉 특별한 검사나 데이터의 재구성이 발생하지 않습니다.

그저 타입 체커의 에러를 없애기 위해 컴파일 과정에서 사용하는 문법입니다.

 

let a;
a = 20;
a = 'hello';

let b = a; // b: any
let b = a as string; // b: string

예시를 보면 a에 마지막으로 문자열 값을 할당했지만 a는 여전히 Any 타입입니다.

그래서 b 또한 Any 타입으로 취급됩니다.

이때 타입 단언을 사용하여 b가 String 타입을 갖게 할 수 있습니다.

 


타입 단언 방법

타입을 단언하는 방법은 2가지가 있습니다.

1. as 키워드

let str: unknown = "this is a string";
let strLength: number = (someValue as string).length;

JSX에서는 as 키워드로만 타입 단언이 가능합니다.

 

 

2. 앵글 브라켓 (angle-bracket, < >)

let str: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

이 방식은 JSX(.tsx)에서 사용할 수 없습니다.

JSX 태그와 혼동되어 파싱에 문제가 발생할 수 있기 때문입니다.

 


타입 선언 vs 타입 단언

type Person = { name: string };

const alice: Person = { name: 'Alice' };
const bob = { name: 'Bob' } as Person;

TypeScript에서 타입을 부여하는 방법은 두 가지가 있습니다.

 

타입 선언은 할당된 값이 타입, 인터페이스를 만족하지 않으면 에러를 발생시킵니다.

타입 단언은 그저 타입 체커가 발생시킨 오류를 무시하도록 만들어줍니다.

결론적으로 타입 선언이 타입 단언보다 안전합니다.

 

const button = document.querySelector('button');  // type: HTMLButtonElement | null

const buttonText = button.innerText  // Object is possibly 'null'


// 타입 단언 - 1. as
const button = document.querySelector('button') as HTMLButtonElement;  // type: HTMLButtonElement

// 타입 단언 - 2. Non-null assertion operator
const button = document.querySelector('button')!;  // type: HTMLButtonElement

const buttonText = button.innerText  // OK

다만 예외적으로 DOM 접근에 있어서는 타입 단언이 자주 사용됩니다.

null로 추정될 가능성이 있다면 DOM 메서드를 사용할 때 오류가 발생하기 때문입니다.

 

 

🔎 Non-null 단언 연산자 (Non-null assertion operator)

const button = document.querySelector('button')!;  // type: HTMLButtonElement

값 뒤에 느낌표(!) 연산자가 붙으면 해당 피연산자가 null, undefined가 아님을 단언할 수 있습니다.

주로 DOM 접근 등에 있어 null 추정으로 인한 오류를 방지하기 위해 사용합니다.

다만 그 값이 null이 아님을 확신할 수 있을 때 사용해야 합니다.