이펙티브 타입스크립트 - 1장

s2ksh77·2023년 3월 3일
0

FrontEnd

목록 보기
5/8

강의와 함께 스터디하면서 훑어보기 한 내용을 정리해보려고 한다.

Item 1 타입스크립트와 자바스크립트의 관계 이해하기

TypeScript와 JavaScript 관계 이해하기

  • TypeScript는 JavaScript의 슈퍼셋이며, JavaScript와 호환됩니다.
  • 따라서 JavaScript의 기본 개념과 구조를 잘 이해해야 TypeScript를 잘 다룰 수 있습니다.
  • 타입시스템의 목표 중 하나는 런타임에 오류를 발생시킬 코드를 미리 찾아내는 것이다.
  • 타입스크립트가 '정적'타입 시스템이라는 것은 바로 이런 특징을 말한다. 단, 타입 체커가 모든 오류를 찾아내지는 않는다.

타입스크립트 설정 이해하기

noImplictAny

  • 변수들이 미리 정의된 타입을 가져야 하는 지 여부를 제어
// tsConfig: {"noImplicitAny":false}
function add(a, b) {
  return a + b;
}

// tsConfig: {"noImplicitAny":true}
function add(a, b) {
          // ~    Parameter 'a' implicitly has an 'any' type
          //    ~ Parameter 'b' implicitly has an 'any' type
  return a + b;
}

strictNullChecks

  • null과 undefined가 모든 타입에서 허용되는지 확인하는 설정
// tsConfig: {"noImplicitAny":true,"strictNullChecks":false}
const x: number = null;  // OK, null is a valid number

// tsConfig: {"noImplicitAny":true,"strictNullChecks":true}
const x: number = null;
//    ~ Type 'null' is not assignable to type 'number'
  • noImplictAny설정때와 마찬가지로, null이나 undefined를 사용하고 싶다면 의도적으로 타입에 명시하면 사용가능
  • 만약 null을 허용하지 않으면 이 값이 어디서부터 왔는지 찾아야 하고, null을 체크하는 코드나 타입 단언문(assertion, !)을 추가

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

  • 타입 오류가 있는 코드도 컴파일 가능하다.
  • 런타임에는 타입 체크가 불가능하다.
  • 타입 연산은 런타임에 영향을 주지 않는다.
  • 런타임 타입은 선언된 타입과 다를 수 있다.
  • 타입스크립트 타입으로는 함수를 오버로드할 수 없다.
  • 타입스크립트 타입은 런타임 성능에 영향을 주지 않는다.

구조적 타이핑에 익숙해지기

  • 자바스크립트가 덕 타이핑 기반이고 타입스크립트가 이를 모델링하기 위해 구조적 타이핑을 사용함을 이해해야 한다.
  • 어떤 인터페이스에 할당 가능한 값이라면 타입 선언에 명시적으로 나열된 속성들을 가지고 있다.
interface Vector2D {
  x: number;
  y: number;
}
function calculateLength(v: Vector2D) {
  return Math.sqrt(v.x * v.x + v.y * v.y);
}
interface NamedVector {
  name: string;
  x: number;
  y: number;
}
const v: NamedVector = { x: 3, y: 4, name: 'Zee' };
calculateLength(v);  // OK, result is 5
  • calculateLength 함수에 인자값이 Vector2D 타입이 아닌 NamedVector타입이 들어갔어도 에러가 발생하지 않는다.
  • 이유는 자바스크립트의 런타임 동작을 모델링하기 때문이다. NamedVector구조가 Vector2D와 호환되기 때문에 호출이 가능하다.
interface Vector2D {
  x: number;
  y: number;
}
function calculateLength(v: Vector2D) {
  return Math.sqrt(v.x * v.x + v.y * v.y);
}
interface NamedVector {
  name: string;
  x: number;
  y: number;
}
interface Vector3D {
  x: number;
  y: number;
  z: number;
}
function normalize(v: Vector3D) {
  const length = calculateLength(v);
  return {
    x: v.x / length,
    y: v.y / length,
    z: v.z / length,
  };
}

normalize({x: 3, y: 4, z: 5}) // { x: 0.6, y:0.8, z: 1}
  • 위와 같은 구조적 타이핑 관점에서 Vector3D타입이 x, y를 가지고 있기 때문에 Vector2D와 호환이 되어 타입문제는 발생하지않고, 의도한 바와 다르게 계산이 된다.

any 타입 지양하기

any 타입에는 타입 안전성이 없다.

  • any를 사용하면 선언된 타입 외에 다른 타입도 할당할 수 있게 된다.

any는 함수 시그니처를 무시해버린다.

  • 함수를 작성할 때는 시그니처를 명시해야 한다. 호출하는 쪽은 약속된 타입의 입력을 제공하고, 함수는 약속된 타입의 출력을 반환한다.
  • 하지만 any 타입을 사용하면 이런 약속을 어길 수 있게 된다.

any 타입에는 언어 서비스가 적용되지 않는다.

  • 자동완성 기능의 도움을 받을 수 없다.
  • 전체 이름을 변경할 때도 도움을 받을 수 없다.

any 타입은 코드 리팩터링 때 버그를 감춘다

any는 타입 설계를 감춰버린다.

  • 타입스크립트에서 제대로 된 타입 설계는 필수이다. 하지만 any타입을 사용하면 타입 설계가 불분명해진다.
  • 설계가 잘 되었는지 설계가 어떻게 되어 있는지 전혀 알 수 없다.

any는 타입시스템의 신뢰도를 떨어뜨린다.

  • 타입스크립트를 사용하면 타입 체커가 실수를 잡아주고 코드의 신뢰도가 높아진다.
  • 그러나 런타임에 타입 오류를 발견하게 된다면 타입 체커를 신뢰할 수 없다.
  • any 타입을 쓰지 않으면 런타임에 발견될 오류를 미리 잡을 수 있고 신뢰도를 높일 수 있다.

결론 -> any 타입 대신 unknown 타입 사용하기

1장 정리 끝.

profile
오너십을 가지고 끊임없이 더 나은 방향을 고민하는 개발자 입니다. 새로운 기술을 적용하고 배우는 것을 좋아합니다.

0개의 댓글