타입스크립트 알아보기2

이펙티브 타입스크립트를 읽고 공부한 것을 기록합니다.

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

{
  "compilerOptions:{
    "noImplicity":true
  }
}

타입스크립트는 타입 정보를 가질 때 가장효과적이기에, 되도록이면 noImplicitAny를 설정해줘야 한다. 모든 변수에 타입을 명시하는 것에 익숙해지면, noImplicitAny가 없는 채로 작성된 타입스크립트는 완전히 다른 언어처럼 느껴질 것이다.

새 프로젝트를 시작한다면 처음부터 noImplicitAny를 설정하여 코드를 작성할 때마다 타입을 명시하도록 해야한다. 그러면, 타입스크립트가 문제를 발견하기 수월해지고, 코드의 가독성이 좋아지며, 개발자의 생산성이 향상된다. noImplicitAny설정 해제는 자바스크립트로 되어있는 기존 프로젝트를 타입스크립트로 전환하는 상황에만 필요하다.

요약

  • 타입스크립트 컴파일러는 언어의 핵심 요소에 영향을 미치는 몇 가지 설정을 포함하고 있다.
  • 타입스크립트 설정은 커맨드 라인을 이용하기보다는 tsconfig.json을 사용하는 것이 좋다.
  • 자바스크립트 프로젝트를 타입스크립트로 전환하는게 아니라면 noImplicitAny를 설정하는 것이 좋다.
  • undefined는 객체가 아닙니다같은 런타임 오류를 방지하기 위해 strictNullCheck를 설정하는 것이 좋다.
  • 타입스크립트에서 엄격한 체크를 하고 싶다면 strict설정을 고려해야 한다.

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

타입스크립트 컴파일러는 두 가지 역할을 수행한다.

  1. 최신 타입스크립트/자바스크립트를 브라우저에서 동작할 수 있도록 구버전의 자바스크립트로 트랜스파일한다.
    2.코드의 타입 오류를 체크한다.

타입 오류가 있는 코드도 컴파일이 가능하다 컴파일은 타입체크와 독립적으로 동작하기에 타입오류가 있는 코드도 컴파일이 가능하다.

런타임에는 타입체크가 불가능하다

interface Square {
  width: number
}

interface Rectangle extends Square {
  height: number
}

type Shape = Square | Rectangle

function calculateArea(shape: Shape) {
  if (shape instanceof Rectangle) {
    return shape.width * shape.height
  } else {
    return shape.width * shape.width
  }
}

instanceof 체크는 런타임에 일어나지만, Rectangle은 타입이기에 런타임 시점에 아무런 역할을 할 수 없다.

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

자바스크립트는 본질적으로 덕 타이핑 기반이다. 만약 어떤 함수의 매개변수 값이 모두 제대로 주어진다면, 그 값이 어떻게 만들어졌는지 신경쓰지 않고 사용한다. 타입스크립트는 매개변수 값이 요구사항을 만족한다면 타입이 무엇인지 신경쓰지 않는 동작을 그대로 모델링한다. 구조적 타이핑을 제대로 이해한다면 오류인 경우와 오류가 아닌 경우의 차이를 알 수 있고, 더욱 견고한 코드를 작성할 수 있다.

interface Vector 2D {
  x:number;
  y:number;
}
interface Vector 3D{
  x:number;
  y:number;
  z:number;
}
function calculateLength(v:Vector2D){
  return Math.sqrt(v.x*v.x+v.y*v.y)
}

function normalize(v:Vector3D) {
  const length = calculateLength(v);
  return{
    x:v.x/length;
    y:v.y/length;
    z:v.z/length;
  }
}
// 이 함수는 1보다 조금 더 긴(1.41)길이를 가진 결과를 출력할 것이다.
> normalize({x:3,y:4,z:5})

타입스크립트가 오류를 잡지 못한 이유를 생각해보면, calculateLength는 2D 벡터를 기반으로 연산하는데, 버그로 인해 normalize가 3D벡터로 연산되었다. z가 정규화에서 무시된 것이다. 그런데 타입체커가 이 문제를 잡아내지 못했다. calculateLength가 2D벡터를 받도록 선언되어있음에도 3D벡터를 받는데 문제가 없었던 이유는 무엇일까?

Vector3D와 호환되는 {x,y,z}객체로 calculateLength를 호출하면, 구조적 타이핑 관점에서 x와 y가 있어서 Vector2D로 호환된다. 따라서 오류가 발생하지 않았고, 타입체커가 문제로 인식하지 않았다.

요약

  • 자바스크립트가 덕 타이핑기반이고 타입스크립트가 이를 모델링하기 위해 구조적 타이핑을 사용함을 이해해야 한다. 어떤 인터페이스에 할당 가능한 값이라면 타입선언에 명시적으로 나열된 속성들을 가지고 있을 것입니다. 타입은 봉인되어있지 않다.
  • 클래스 역시 구조적 타이핑 규칙을 따른다는 것을 명심해야 한다.

any타입 지양하기

일부 특별한 경우를 제외하고는 any를 사용하면 타입스크립트의 수많은 장점을 누릴 수 없게 된다. 부득이하게 any를 사용하더라도 그 위험성을 알고 있어야 한다

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

any타입은 타입 설계를 감춘다 애플리케이션 상태 같은 객체를 정의하려면 꽤 복잡하다. 상태 객체 안에 있는 수많은 속성의 타입을 일일이 작성해야 하는데, any타입을 사용하면 간단히 끝내버릴 수 있다. 물론 이때도 any를 사용하면 안된다.any를 사용하면 타입 설계가 불분명해진다. 설계가 명확히 보이도록 타입을 일일이 작성하는게 좋다.

any는 타입시스템의 신뢰도를 떨어뜨린다 타입체커가 실수를 잡아주고 코드의 신뢰도를 높일 수 있다.any타입을 쓰지 않으면 런타임에 발견될 오류를 미리 잡을 수 있고 신뢰도를 높일 수 있다.

요약

  • any타입을 사용하면 타입체커와 타입스크립트 언어 서비스를 무력화시켜버린다. any타입은 진짜 문제점을 감추며, 개발경험을 나쁘게 하고, 타입시스템의 신뢰도를 떨어뜨린다. 최대한 사용을 피하도록 합시다.

✓ 생각 정리

타입스크립트를 쓰고 있지만, 여전히 모르는 부분이 많다고 느껴져서 이펙티브타입스크립트 공부를 시작했다. 여전히 타입에러는 많이나고 어쩔 수 없이 any를 많이 쓰고 있는 나를 볼 때, 더 공부가 필요하다는 생각이 많이 든다. 이번 파트를 공부하며 새 프로젝트에 noImplicitAny를 설정하여 코드를 작성할 때마다 타입을 명시하도록 해줬다! 이펙티브 타입스크립트 책을 보면 이해가 잘 안되는 부분이나 지금 나에게 필요하지 않아보이는 내용도 있었다. 그 부분은 스킵하고 필요한 부분이라고 생각하는 부분만 집중적으로 읽고 공부를 해볼 계획이다-!


Written by@
기록하는 것을 좋아하는 프론트엔드 개발자👩🏻‍💻

GitHubLinkedIn