본문 바로가기
Typescript

[TypeScript] 이펙티브 타입스크립트 정리 - 아이템 1 ~ 5

by 맨날개발 2025. 6. 1.
이펙티브 타입스크립트 읽고 정리

🎤 소개

프로젝트에 타입스크립트를 사용할때 API에서 받아오는 데이터 또는 함수의 인자에 타입을 정의하는 용도 위주로만 타입스크립트를 활용하였다. 타입에러가 발생했을 때 아직 깊은 부분까지 알지 못하다보니 왜 문제가 발생했고, 어떻게 해결해야할지 명확한 방법을 알지 못한채 타입 단언 등으로 임시방편 처리만 하는 일이 잦았다.

 

그래서 타입스크립트에 대한 공부를 더 해야겠다는 생각이 들어 이펙티브 타입스크립트를 공부하게 되었다. 책을 읽기 전에는 나름 타입스크립트에 대해서 어느정도는 알고 있었다고 생각했으나, 책을 모두 보고 나니 지금까지는 수박 겉 핥기로만 해왔다는 걸 느꼈다. 

 

그래서 타입스크립트에 대해서 좀 더 깊이있게 공부하고 싶거나, 타입스크립트의 활용방안에 대해서 알고 싶다면 책을 추천한다.

 

 

1️⃣ 아이템 1. 타입스크립트와 자바스크립트의 관계 이해하기

1. 타입스크립트는 자바스크립트의 상위집합이다.

 

 

2. 자바스크립트 프로그램을 타입스크립트 프로그램이다.

  • 이 말은, 자바스크립트로 만들어진 모든 프로그램은 타입스크립트로도 실행이 가능하다는 것이다.

 

3. 타입스크립트 프로그램은 자바스크립트 프로그램이 아닐 수 있다.

  • 타입스크립트로 만들어진 프로그램은 자바스크립트에서 실행되지 않을 수 있다.
  • 타입 구문의 추가 및 타입스크립트에서만 동작하는 문법 추가

 

4. 타입 체커를 통과하면서 런타임 오류를 발생시키기도 한다.

  • 아래의 코드는 타입 체커는 통과하지만, 실제로 실행시키면 에러가 발생하게 된다.
const names = ['Hello', 'World'];
names[3].toUpperCase();

 

 

2️⃣ 아이템 2. 타입스크립트 설정 이해하기

{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}
  • noImplicitAny : 변수들이 미리 정의된 타입을 가져야 하는지 여부를 설정. 해당 설정을 사용하지 않고 타입을 지정하지 않으면 변수는 암시적으로 any 타입을 가지게 된다.
  • strictNullChecks : null와 undefined를 모든 타입에서 허용할지를 결정한다. 해당 설정을 사용하지 않는 다면 number 타입인 변수에 null 값을 할당할 수 있다.
타입스크립트를 제대로 사용하기 위해서는 두 설정 모두 true 로 설정해야 한다.

 

 

3️⃣ 아이템 3. 코드 생성과 타입이 관계 없음을 이해하기

타입과 코드의 실행과는 무관하다. 그래서 타입 체크에서 오류가 발생하더라도 컴파일이 가능하다. 타입 체크는 컴파일이전 시점까지만 유효하기 때문에 런타임에서는 타입 체크가 불가능하다.

 

왜냐하면 브라우저에서 해석 가능한 언어는 자바스크립트뿐이기 때문에 컴파일 시점에서 타입과 관련한 구문은 모두 제거되어진다.

 

타입스크립트에서는 런타임 타입과 선언된 타입이 다를 수 있음을 인지해야한다. 왜냐하면 런타임에서는 선언된 타입과 무관한 타입의 값을 모두 사용이 가능하다.

 

아래와 같이 fn 이라는 함수는 인자로 숫자 타입을 전달받는다. fn 함수를 호출할 때 숫자타입이 아닌 타입을 전달하는 경우 타입에러가 발생하지만 런타임 시점에서는 어떠한 타입을 전달하더라도 호출 시점에서는 에러가 발생하지 않는다.

function fn(num: number) {}

 

이 차이에 유념하여 코드를 작성해주어야 한다.

 

타입스크립트에서 함수 오버로딩 기능을 지원하기는 하지만, 타입 수준에서만 동작하고 실제 구현은 하나만 가능하다.

 

타입과 관련 된 코드는 모두 제거되기 때문에 런타임 성능에 영향을 주지 않는다. 대신 컴파일 시점에 빌드타임 오버헤드가 있을 수 있다.

 

 

4️⃣ 아이템 4. 구조적 타이핑에 익숙해지기

자바스크립트에서부터 덕 타이핑 기반으로 동작하는데, 타입스크립트도 이를 채택하여 타입에서 덕 타이핑 기반으로 동작한다.

덕 타이핑이란 어떤 타입에 속한 변수와 메서드만 충족한다면 타입에 속하는 것으로 간주하는 방식이다.

 

아래의 fn 함수에 서로 다른 타입의 값을 전달하지만 덕 타이핑에 의해 타입이 통과된다.

interface Vector2D {
  x: number;
  y: number;
} 

interface Vector3D {
  x: number;
  y: number;
  z: number;
}

function fn(vector2d: Vector2D) {}

const vector3d: Vector3D = {
  x: 1,
  y: 2,
  z: 3
}

fn(vector3d);

 

함수 내부에서 전달받은 객체의 정확한 속성에만 접근한다면 문제가 발생하지 않겟지만 아래와 같은 코드를 사용하게 되면 타입 에러가 발생하게 된다.

function fn(vector2d: Vector2D) {
  for (const key of Object.keys(vector2d)) {
    console.log(vector2d[key]);
  }
}

 

그 이유는 덕 타이핑에 의해 추가 되어지는 속성에 대해서는 체크하지 않기 때문에 Object.keys로 추출된 결과에서는 Vector2D가 가질 수 있는 속성 이상의 결과가 나올 수 있기 때문이다.(예를 들어 Vector3D 값을 전달했다면 z이다.)

 

이를 통해 예상치 못한 결과를 만들어낼 수 있기 때문에 타입스크립트에서는 에러를 발생시킨다. 그래서 반복횟수가 크지 않다면 직접 각 속성에 접근해서 처리하는 것이 좋다.

function fn(vector2d: Vector2D) {
  console.log(vector2d.x);
  console.log(vector2d.y);
}

 

 

5️⃣ 아이템 5. any 타입 지양하기

보통 타입 작성에 문제가 발생했을 때 이를 간단하게 해결하기 위해서 any를 많이 쓰곤한다. 하지만 이는 타입스크립트의 이점을 포기하는 행동이기 때문에 특별한 경우가 아니라면 지양해야한다.

 

any는 모든 타입을 전달받을 수 있다. any를 사용한다는 건 타입을 사용하지 않는 것과 동일하다.

  • 타입 안전성이 없다.
  • 함수 시그니처를 무시한다.
  • 언어 서비스의 도움을 받을 수 없다.
  • 타입시스템의 신뢰도를 떨어뜨린다.