개발자가 되고 싶은 개발자

[TypeScript] 이펙티브 타입스크립트-(Part.1) 2장 타입스크립트의 타입 시스템 본문

Dev/JavaScript & TypeScript

[TypeScript] 이펙티브 타입스크립트-(Part.1) 2장 타입스크립트의 타입 시스템

Fullth 2022. 4. 25. 22:00
 

이펙티브 타입스크립트 - YES24

타입스크립트는 타입 정보를 지닌 자바스크립트의 상위 집합으로, 자바스크립트의 골치 아픈 문제점들을 해결해 준다. 이 책은 《이펙티브 C++》와 《이펙티브 자바》의 형식을 차용해 타입스

www.yes24.com

 

GitHub - fullth/effective-typescript: Effective TypeScript: 62 Specific Ways to Improve Your TypeScript

Effective TypeScript: 62 Specific Ways to Improve Your TypeScript - GitHub - fullth/effective-typescript: Effective TypeScript: 62 Specific Ways to Improve Your TypeScript

github.com

목차

Part.1

ITEM06 편집기를 사용하여 타입 시스템 탐색하기

  • 타입스크립트의 가장 중요한 역할은 타입 시스템
  • 타입스크립트를 설치하면 할 수 있는 일
    • 타입스크립트 컴파일러(tsc)
    • 단독 실행 가능한 타입스크립트 서버(tsserver)
  • 타입스크립트 서버는 '언어 서비스'를 제공한다는 점에서 중요
    • 코드 자동 완성, 명세 검사, 검색, 리펙터링이 포함.
  • 편집기에서의 타입스크립트 언어 서비스를 통해 타입 시스템의 동작, 어떻게 타입을 추론하는지 개념을 잡을 수 있음.

=> 제공되는 서비스를 적극 활용하여 타입 추론의 개념을 익히자

ITME07 타입의 값들이 집합이라고 생각하기

  • 런타임에 모든 변수는 자바스크립트 환경의 값으로부터 정해지는 각자의 고유한 값을 가짐.
  • 타입을 '할당 가능한 값들의 집합'이라고 생각하자.
    • 이 집합을 타입의 '범위'라고 부르기도 한다.
  • 가장 작은 집합은 공집합. 타입 스크립트에서는 never 타입. 아무런 값도 할당할 수 없음.
  • 그 다음으로 작은 집합은 한 가지 값만 포함하는 타입.
    • 타입스크립트에서 유닛 타입이라고도 불리는 리터럴 타입.
type A = 'A';
type B = 'B';
type Twelve = 12;
  • 두 개 혹은 세 개로 묶으려면 유니온 타입을 사용
    • 유니온 타입은 값 집합들의 합집합을 일컫음.
type AB = 'A' | 'B';
type AB12 = 'A' | 'B' | 12;
  • 타입스크립트의 오류 중 '할당 가능한'이라는 문구
    • 집합의 관점에서 '~의 원소' 또는 '~의 부분 집합'을 의미
    • "C"는 한 가지 값만 포함하는 유닛 타입. AB의 부분집합 (A or B)가 아니므로 오류.
  • 타입 체커의 주요 역할은 하나의 집합이 다른 집합의 부분집합인지 검사하는 것.
interface Identified {
  id: string;
}
  • 어떤 객체가 string으로 할당가능한 id 속성을 가지고 있다면 그 객체는 Identified.
    • 구조적 타이핑 규칙들은 어떠한 값이 다른 속성도 가질 수 있음을 의미. (아이템 4)
interface Identified {
  id: string;
}
interface Person {
  name: string;
}
interface Lifespan {
  birth: Date;
  death?: Date;
}
type PersonSpan = Person & Lifespan;
  • 두 인터페이스의 공통 사항이 있어 공집합으로 오해하기 쉬우나, 타입 연산자는 인터페이스의 속성이 아닌,
    값의 집합(타입의 범위)에 적용됨.
    • 그래서 둘 다 가지는 값은 인터섹션 타입에 속하게 됨.
    • 인터섹션 타입의 값은 각 타입 내이 속성을 모두 포함하는 것이 일반적.
    • 유니온에는 그렇지 않음. 유니온 타입에 속하는 값은 어떤 키도 없기 때문에.
interface Identified {
  id: string;
}
interface Person {
  name: string;
}
interface Lifespan {
  birth: Date;
  death?: Date;
}
type PersonSpan = Person & Lifespan;
const ps: PersonSpan = {
  name: 'Alan Turing',
  birth: new Date('1912/06/23'),
  death: new Date('1954/06/07'),
};  // OK

=> 타입을 값들의 집합이라 생각하면 타입을 이해하기 쉽다.

ITME08 타입 공간과 값 공간의 심벌 구분하기

  • Symbol은 타입 공간이나 값 공간 중 한 곳만 존재함.
    • 이름이 같더라도 속하는 공간에 따라 다른 것을 나타낼 수 있음.
  • 모든 값은 타입을 갖지만, 타입은 값을 갖지 않음.
interface Cylinder {
  radius: number;
  height: number;
}

const Cylinder = (radius: number, height: number) => ({radius, height});
function calculateVolume(shape: unknown) {
  if (shape instanceof Cylinder) {
    shape.radius
       // ~~~~~~ Property 'radius' does not exist on type '{}'
  }
}

ITME09 타입 단언보다는 타입 선언을 사용하기

  • 타입 단언을 사용할 경우 타입 체커가 발견한 오류를 무시함.
  • 꼭 필요한 경우가 아니라면 타입 선언을 사용하는 것이 좋음.

=> 타입 단언 as ... 보다 타입선언 x: number을 사용할 것.

ITME10 객체 래퍼 타입 피하기

  • 객체 래퍼 타입을 지양하고, 기본형 타입을 사용해야 함.
function getStringLen(foo: String) {
  return foo.length;
}

getStringLen("hello");  // OK
getStringLen(new String("hello"));  // OK

function isGreeting(phrase: String) {
  return [
    'hello',
    'good day'
  ].includes(phrase);
          // ~~~~~~
          // Argument of type 'String' is not assignable to parameter
          // of type 'string'.
          // 'string' is a primitive, but 'String' is a wrapper object;
          // prefer using 'string' when possible
}

ITME11 잉여 속성 체크의 한계 인지하기

  • 일전의 구조적 타이핑 관점에서 아래의 예제보기
interface Room {
  numDoors: number;
  ceilingHeightFt: number;
}
const r: Room = {
  numDoors: 1,
  ceilingHeightFt: 10,
  elephant: 'present',
// ~~~~~~~~~~~~~~~~~~ Object literal may only specify known properties,
//                    and 'elephant' does not exist in type 'Room'
};

interface Room {
  numDoors: number;
  ceilingHeightFt: number;
}
const obj = {
  numDoors: 1,
  ceilingHeightFt: 10,
  elephant: 'present',
};
const r: Room = obj;  // OK
  • 객체에 타입을 선언하고 값에 추가적인 값을 할당하는 것과, 객체를 바로 할당하는 것의 차이는 잉여 속성 체크와 할당 가능 검사가 별도의 과정이 별도의 과정이라는 점을 알아야 한다.

ITME12 함수 표현식에 타입 적용하기

  • 타입스크립트에서는 함수 표현식을 사용하는 것이 좋음.
    • 함수의 매개변수부터 반환값까지 전체를 함수 타입으로 선언해 함수 표현식에 재사용할 수 있는 장점이 있기 때문.