TypeScript의 Soundness와 Type Assertion (as 떡칠하지 말자..)

2022-09-24

우선 TypeScript의 타입 시스템에 대해 이야기하는게 좋겠다.

  • Soundness의 반대개념인 Unsoundness가 런타임에 문제를 유발할 수 있지만 TypeScript는 일부 불건전한 동작을 허용한다.

Soundness

  • 컴파일 타임에 알기 어려운 특정 타입을 안전하게 허용하는 것을 의미한다.
    • 즉 컴파일러가 런타임 시점 값의 타입을 보장할 수 있다는 개념
    • 모든 JavaScript 코드를 지원하기 위함
    • 타입스크립트는 변환된 코드가 런타임에 영향을 미치지 않는 것을 목표로 한다.

일부 불건전한 코드에는 any도 있을 수 있고, as도 있을 수 있겠다.

Type Assertion에 대한 이야기를 해보자.

Type Assertion

  • 타입 단언
  • 타입 추론에는 어쩔 수 없는 한계가 존재하기 때문에
    사용자가 타입을 가장 잘 알고 있다는 것을 명시하는 방법
const num = "1000" as unknown as number;
const cat = {
  name: "moo",
  age: 10,
} as const;

  • 객체의 모든 프로퍼티들이 readonly로 변경된다.

  • 각 프로퍼티의 타입이 할당된 리터럴 값으로 추론된다.

  • 값의 재할당을 막는다.

  • 추론 범위를 좁혀준다.
    -> 의도치 않은 오류를 없앨 수 있다.

  • 하지만 타입캐스팅과는 다르다!

  • 타입 단언은 컴파일단에서만 타입을 변경한다. 런타임에 영향을 주지 않는다.

  • 어쩔 수 없는 경우를 제외하고 as를 떡칠하는 경우는 any를 쓰는 것과 같다. (any를 떡칠할거면 TypeScript를 쓰지 않는게 더 낫겠지..)

내가 어떨때 as를 썼더라..🧐

  • ref 달아서 이벤트핸들러 만들때 자주 쓰게 되었던 것 같다.
  • DOM api 조작시에도 많이 사용했던 것 같고?
const div = document.querySelector("div") as HTMLDivElement;

그렇다면 최대한 쓰지 않으려면 어떻게 해야할까?

  • as를 쓰기 전에 TypeScript가 내 코드를 왜 추론하지 못하는지 살펴보자.
  • 타입가드를 이용해 최대한 타입을 좁혀주자.
  • instanceofnew.target을 통해 타입가드를 해준다.