#3 코드 생성과 타입이 관계없음을 이해하기

2022. 12. 15.·🎨 프론트엔드 공부/JS & TS

이펙티브 타입스크립트 (댄 밴더캄 지음) 를 읽고 정리

📍타입 에러가 있는 코드도 컴파일이 가능

- 타입 체크와 컴파일은 독립적으로 동작

- 문제가 있는 부분을 알려주지만, 빌드가 중단되지는 않음

- tsconfing.json에서 noEmitOnError를 설정하면 타입 에러일 때 컴파일 X

📍런타임에는 타입 체크 불가

- 런타임에서는 타입을 활용할 수 없다

아래 코드에서 그 예시를 확인할 수 있다

interface Square {
    width: number;
}

interface Rectangle extends Square {
    height: number;
}

type Shape = Square | Rectangle;

function calculateArea(shape: Shape) {
    if (shape instanceof Rectangle) { // 에러 : Rectangle 타입이 값으로 사용됨
        return shape.width * shape.height; // 에러 : Shape 타입에 height가 없음
    } else {
        return shape.width * shape.width;
    }
}

 

-  타입스크립트의 타입은 제거 가능하다 (자바스크립트로 컴파일 되는 과정에서 실제로 제거됨)

위 코드의 에러를 해결하는 방법 (런타임에 타입을 지정하는 방법) 3가지가 있다

 

1️⃣런타임에서 프로퍼티(값) 체크

타입 체커가 shape 타입을 Rectangle로 보정해줌

interface Square {
    width: number;
}

// Rectangle 타입은 Square 타입을 확장
interface Rectangle extends Square {
    // width: number 도 필요
    height:  number;
}

const v: Rectangle = { // width 프로퍼티 없어서 에러 발생
    height: 2
}

// 런타임에 타입 정보를 유지할 수 있음
type Shape = Square | Rectangle;

function calculateArea(shape: Shape) {
    if ("height" in shape) { // 런타임에서 shape를 Rectangle로 자동 보정
        return shape.width * shape.height;
    } else {
        return shape.width * shape.width;
    }
}

 

2️⃣tagged union 으로 런타임에서 타입 정보를 유지

런타임에서 접근 가능한, 명시적인 타입 정보 프로퍼티를 사용해서 타입 정보 유지

interface Square {
    kind: "square",
    width: number;
}

interface Rectangle {
    kind: "rectangle",
    width: number,
    height: number;
}

type Shape = Square | Rectangle;

function calculateArea(shape: Shape) {
    if (shape.kind === "rectangle") {
        return shape.width * shape.height;
    } else {
        return shape.width * shape.width;
    }
}

 

위의  두 타입을 클래스로 만들 수도 있다.

3️⃣클래스를 사용하면, 타입과 값을 둘 다 사용할 수 있다

class Square {
    constructor(public width: number) {}
}

class Rectangle extends Square {
    constructor(public width: number, public height: number) {
        super(width);
    }
}

type Shape = Square | Rectangle;

function calculateArea(shape: Shape) {
    // shape가 Rectangle 타입임
    if (shape instanceof Rectangle) { // 런타임에서 shape를 Rectangle로 자동 보정
        return shape.width * shape.height;
    } else {
        return shape.width * shape.width;
    }
}

 

📍타입 연산은 런타임에 영향을 주지 않는다

타입 체커를 통과하지만 잘못된 방법을 쓴 코드

// string or number 타입인 값을 항상 number로 바꾸는 함수
function asNumber(val: number | string): number {
    return val as number; // 타입 단언문 (assertion)
}

// 컴파일된 자바스크립트 코드
function asNumber(val) {
    // 어떠한 정제 과정도 없음
    return val;
}

 

이렇게 바꿔야 한다

// string or number 타입인 값을 항상 number로 바꾸는 함수
function asNumber(val: number | string): number {
    return typeof(val) === "string" ? Number(val) : val;
}

// 컴파일된 자바스크립트 코드
function asNumber(val) {
    return typeof (val) === "string" ? Number(val) : val;
}

 

📍타입스크립트 타입으로는 함수 오버로딩이 불가능

- 함수 오버로딩 : 동일한 이름에 매개변수만 다른 여러 버전의 함수를 허용하는 것

타입스크립트에서는 타입과 런타임의 동작이 무관하기 때문에 함수 오버로딩 불가

// 중복된 함수 구현으로 에러 발생
function add(a: number, b: number) {
    return a + b;
}
// 중복된 함수 구현으로 에러 발생
function add(a: string,  b: string) {
    return a + b;
}

 

- 단지 타입 수준의 함수 오버로딩만 가능

하나의 함수에 대해 여러 선언문(콜 시그니처)을 작성할 수 있지만, 구현체는 단 하나

// 여러 콜 시그니처를 만들 수 있음
function add(a: number, b: number): number;
function add(a: string, b: string): string;

📍타입스크립트 타입은 런타임 성능에 영향을 주지 않음

- 타입과 타입 연산자는 컴파일 시점에 제거되므로, 런타임 성능에 영향 X

=> 런타임 오버헤드가 없는 대신 (컴파일로 인한)빌드타임 오버헤드는 있다

 

- 가령, 이러한 경우가 있을 수 있음

제네레이터 함수가 ES5 타겟으로 컴파일되려면, 타입스크립트 컴파일러는 호환성을 위한 헬퍼 코드를 추가해야 함

- 호환성을 높이기 위해 성능 오버헤드를 감수할지? (헬퍼 코드 작성으로 인한)

- 성능 중심의 네이티브 구현체(ES6+ 스펙)를 선택할지? (트랜스파일링 X)

 

=> 이는 타입과 무관하다!!

'🎨 프론트엔드 공부/JS & TS' 카테고리의 다른 글
  • #5 any 타입 지양하기
  • #4 구조적 타이핑에 익숙해지기
  • #2 타입스크립트 설정 이해하기
  • #1 타입스크립트와 자바스크립트의 관계 이해하기
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (516)
      • 🎨 프론트엔드 공부 (253)
        • JS & TS (92)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
#3 코드 생성과 타입이 관계없음을 이해하기
상단으로

티스토리툴바