ts-for-jsdev
  • 자바스크립트 개발자를 위한 타입스크립트
  • 들어가며
  • 01 타입스크립트 소개
    • 1.0 들어가며
    • 1.1 정적 타입 분석
    • 1.2 왜 타입스크립트인가
    • 1.3 타입스크립트의 구성요소
    • 1.4 타입스크립트의 역사
  • 02 ECMAScript
    • 2.0 ECMAScript
    • 2.1 블록 수준 스코프
      • 2.1.1 let을 이용한 선언
      • 2.2.2 const를 이용한 선언
      • 2.2.3 스코프 베스트 프랙티스
    • 2.2 객체와 배열
      • 2.2.1 비구조화 할당
      • 2.2.2 나머지 연산자와 전개 연산자
      • 2.2.3 객체 리터럴 변경사항
    • 2.3 함수
      • 2.3.1 기본 매개변수
      • 2.3.2 화살표 함수
    • 2.4 템플릿 리터럴
      • 2.4.1 멀티라인 문자열
      • 2.4.2 문자열 치환
    • 2.5 원소 순회
      • 2.5.1 forEach 메소드
      • 2.5.2 for-of 문법
      • 2.5.3 이터레이터 프로토콜
      • 2.5.4 이터러블 프로토콜
    • 2.6 비동기 처리
      • 2.6.1 프로미스
      • 2.6.2 Async / Await
    • 2.7 맺으며
  • 03 타입스크립트 기초 문법
    • 3.0 타입스크립트 기초 문법
    • 3.1 기본 타입
    • 3.2 배열과 튜플
    • 3.3 객체
    • 3.4 타입 별칭
    • 3.5 함수
    • 3.6 제너릭
    • 3.7 유니온 타입
    • 3.8 인터섹션 타입
    • 3.9 열거형
  • 04 인터페이스와 클래스
    • 4.0 들어가며
    • 4.1 인터페이스 기초
    • 4.2 색인 가능 타입
    • 4.3 인터페이스 확장
    • 4.4 클래스
    • 4.5 클래스 확장
    • 4.6 클래스 심화
      • 4.6.1 스태틱 멤버
      • 4.6.2 접근 제어자
      • 4.6.3 접근자
      • 4.6.4 추상 클래스
    • 4.7 인터페이스와 클래스의 관계
    • 4.8 맺으며
  • 05 타입의 호환성
    • 5.0 들어가며
    • 5.1 기본 타입의 호환성
    • 5.2 객체 타입의 호환성
    • 5.3 함수 타입의 호환성
    • 5.4 클래스의 호환성
    • 5.5 제너릭의 호환성
    • 5.6 열거형의 호환성
    • 5.7 맺으며
  • 06 타입 시스템 심화
    • 6.0 들어가며
    • 6.1 타입 좁히기
    • 6.2 타입 추론
    • 6.3 타입 단언
    • 6.4 집합으로서의 타입
    • 6.5 서로소 유니온 타입
    • 6.6 맺으며
  • 07 고급 타입
    • 들어가며 (7월 2일 공개)
  • 08 모듈과 네임스페이스
    • 들어가며 (7월 16일 공개)
  • 09 실제 프로젝트에서 사용하기
    • 들어가며 (7월 30일 공개)
  • 10 유용한 라이브러리 소개
    • 들어가며 (8월 13일 공개)
    • 맺으며
  • 부록 II : 자바스크립트 언어 생태계
    • ECMAScript 언어 표준과 TC39
    • TC39 프로세스
    • 실제 예시 - Array.prototype.includes
    • 타입스크립트와 ECMAScript
Powered by GitBook
On this page
  • 타입 단언 문법
  • any 타입 단언
  • 다중 단언
  1. 06 타입 시스템 심화

6.3 타입 단언

타입 단언을 통해 컴파일러에게 특정 타입 정보의 사용을 강제할 수 있다.

타입스크립트 컴파일러는 타입 표기, 타입 좁히기와 타입 추론 등의 기법을 이용해 값의 타입을 판단한다. 하지만 때로는 컴파일러가 가진 정보를 무시하고 프로그래머가 원하는 임의의 타입을 값에 할당하고 싶을 수 있다. 이럴 때 필요한 것이 바로 타입 단언(type assertion)이다.

타입 단언 문법

value as Type 문법을 사용해 값 value를 Type 타입으로 단언할 수 있다. 이 표현은 다음과 같은 의미를 갖는다.

value가 어떤 타입인지는 내가 가장 잘 알아. 책임은 프로그래머인 내가 질테니, 네가 갖고 있는 정보는 다 무시하고 value를 Type 타입의 값이라 생각하고 진행해.

일례로 아래 코드는 Animal 타입의 값을 Fish로 단언한다. 원래대로라면 Dog와 Insect 타입에는 swim 메소드가 없다는 에러가 났겠지만, 타입 단언으로 인해 컴파일러는 animal을 Fish 타입으로 해석하고, 타입 에러 없이 컴파일된다.

interface Dog {
  legs: 4;
  bark(): void;
}

interface Insect {
  legs: number;
  creepy: boolean;
}

interface Fish {
  swim(): void;
}

type Animal = Dog | Insect | Fish;

function doSomethingWithAnimal(animal: Animal) {
  (animal as Fish).swim();
}

주의할 점은 타입 단언은 타입 에러를 없애줄 뿐 런타임 에러를 막아주지 않는다는 점이다. 오히려 그 반대인데, 컴파일 타입에 잡을 수 있는 에러를 없앰으로서 원래대로면 생기지 않았을 런타임 에러를 발생시킬 수 있다. 실제로 위 함수는 런타임에 Dog 혹은 Insect 타입 값을 받으면 터질 것이다.

any 타입 단언

3장에서 타입스크립트의 비상 탈출구인 any 타입에 대해 다루었다. 값을 any 타입으로 단언함으로써 특정 값에 대한 타입 검사를 사실상 완전히 무효화할 수 있다.

(3 as any).substr(0, 3);

위 코드는 실제로 실행한다면 런타임 에러가 발생하지만, 타입 검사는 통과한다. 번거로운 타입 검사를 피할 수 있지만, any를 사용한 타입 단언은 어쩔 수 없는 경우를 제외하곤 피하는 것이 좋다. 타입스크립트를 사용하는 근본적인 이유는 런타임에 발생할 에러를 컴파일 타임에 방지하기 위해서인데, any를 사용한 타입 단언은 그 의도에 정확히 반하기 때문이다.

다중 단언

타입 단언은 여러번 겹쳐 사용할 수 있다.

const wowSuchAny = (((42 as any) as any) as any) as any);

이러한 다중 단언은 호환되지 않는 것이 명백한 타입으로의 단언을 가능케 한다. 아래와 같은 타입 단언에선 타입 에러가 발생한다. Dog 타입을 Insect로 취급할 수 없다는 것을 컴파일러가 알기 때문이다.

interface Dog {
  legs: 4;
  bark(): void;
}

interface Insect {
  legs: number;
  creepy: boolean;
}

const dog: Dog = { legs: 4, bark() { console.log('bark') } };
const insect: Insect = dog as Insect;
// error TS2352: Type 'Dog' cannot be converted to type 'Insect'.
//   Property 'creepy' is missing in type 'Dog'.

하지만 이러한 제약은 any로 한 번 타입 단언을 한 뒤, 그 값을 다시 Insect로 단언함으로서 피해갈 수 있다. 일단 any 타입으로 취급된 그 값은 모든 타입에 할당 가능하기 때문이다.

const insect2: Insect = (dog as any) as Insect; // ok

다시 한 번 강조하지만, 타입 단언이 막아주는 건 타입 에러 뿐이다. 절대 런타임 오류가 나지 않을 것이라는 확신이 있거나 런타임 에러가 나도 상관 없는 상황이 아니라면 이런 식으로 호환되지 않는 타입을 any를 거쳐 단언하는 일은 피하는게 좋다.

Previous6.2 타입 추론Next6.4 집합으로서의 타입

Last updated 6 years ago