본문 바로가기
Typescript

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

by 맨날개발 2025. 6. 3.
이펙티브 타입스크립트 읽고 정리
아이템 1 ~ 5 보러가기

 

6️⃣ 아이템 6. 편집기를 사용하여 타입 시스템 탐색하기

타입스크립트를 사용하면 IDE를 통해서 언어 서비스를 제공받을 수 있다.

아래와 같이 변수 num을 선언하면 num 변수의 값은 number 타입이라는 것을 자동으로 추론해주고 확인할 수 있도록 해준다.

let num = 10;

 

 

 

언어서비스를 통해 제공받는 것은 다음과 같다.

  • 에러가 발생했을 때 무엇이 잘못되었는지 파악하는데 용이
  • 값이 어떠한 타입인지를 시각적으로 표현
  • 자동완성 기능 제공

 

7️⃣ 아이템 7. 타입이 값들의 집합이라고 생각하기

타입스크립트에서의 타입은 값들의 집합이라고 생각하면 쉽다. 예를들어 number 타입은 0, 1, 2 등과 같은 숫자들의 집합이다.

기존에 제공하는 타입 뿐 아니라 유니온을 활용해서 새로운 값의 집합을 만들 수도 있다.

 

아래 AB 타입은 'A'와 'B' 값의 모음이기 때문에 'A' 또는 'B' 값만 할당 가능하다.

type AB = 'A' | 'B'

 

 

 

& 연산자는 연결하는 두 타입의 교집합되는 값의 모음이다. 아래와 같이 'A'와 'B'를 &로 연결하는 경우 'A' 이면서 'B' 인 값은 존재하지 않기 때문에 never 타입이 된다.

type AB = 'A' & 'B'

 

&는 객체 타입을 연결할 때 주로 사용한다. 객체에 &로 연결하는 경우 두 객체의 모든 속성을 가진 타입이 된다.

interface Person {
    name: string;
    address: string;
}

interface Tree {
    name: string;
    type: string;
}

type PersonAndTree = Person & Tree;

const a: PersonAndTree = {
    name: '이름',
    type: '나무',
    address: '서울'
}

 

extends는 '~에 할당 가능한' 또는 '~의 부분 집합' 이라는 의미로 받아들이면 쉽다.

 

아래의 코드에서 Vector2D는 Vector1D의 부분집합이다.

 

왜냐하면 Vector1D는 x 속성만 가지면 모두 Vector1D이다. Vector2D는 x에 더해 y 속성까지 존재하는 더 좁은 범위이기 때문에 Vector1D의 부분집합이라 할 수 있다.

interface Vector1D {
    x: number;
}

interface Vector2D extends Vector1D {
    y: number;
}

interface Vector3D extends Vector2D {
    z: number;
}

 

아래의 코드에서 keyof T를 사용하면 전달받은 객체 타입의 키들의 유니온 타입이 된다. 즉 K extends 유니온 타입인 경우 K 또한 유니온타입이 된다. 아래의 K는 'x' | 'y' 타입이 된다.

function sortBy<K extends keyof T, T>(vals: T[], key: K) {

}

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

const points: Point[] = [{ x: 1, y: 1 }];

sortBy(points, 'x');

 

배열이 아닌 아이템의 길이가 정해져있는 튜플 등과 같은 경우에는 동일한 length가 아닌 경우 할당할 수 없다.

지금까지는 잉여 속성을 가지더라도 동일한 타입으로 취급한다고 하였다. 그래서 다음과 같이 배열에 아이템이 하나 더 추가되는 경우에도 동일하게 계산되어 정상적으로 값 할당이 될 것으로 추측된다.

 

하지만 예상과는 다르게 아래의 코드는 타입 에러가 발생한다.

const triple: [number, number, number] = [1,2,3];
const tuple: [number, number] = triple;

 

그 이유는 아래의 타입이 다음과 같다고 할 수 있다. length의 값이 상수 타입으로 지정되어 있는데 이 부분이 다르기 때문에 triple을 tuple에 할당이 불가능하게 된다.

interface Triple { 
    0: number; 
    1: number; 
    2: number; 
    length: 3;
}

interface Tuple {
    0: number; 
    1: number;  
    length: 2;
}

 

 

8️⃣ 아이템 8. 타입 공간과 값 공간의 심벌 구분하기

타입명과 변수명은 중복으로 사용이 가능하다.

interface A {
  name: string;
}

const A: { age: number; } = {
    age: 1
};

function fn(a: A) {
    console.log(a.name);
}

console.log(A.age);

 

하지만 위와 같이 하나의 파일에서 혼용해서 사용하는 경우 해당 심볼이 타입인지 값인지 구분하기가 쉽지 않기 때문에 같은 이름으로 타입과 값을 사용하는 것은 지양하는 것이 좋다.

 

 

속성 접근자인 '[]'는 타입에서도 동일하게 사용할 수 있다. 이때 A.name은 불가능하다.

interface A {
  name: string;
}

type NameType = A['name']

 

이때 유니온 타입과 기본형 타입을 포함한 어떤 타입이든 사용가능하다.

interface A {
  name: string;
  age: string;
}

type AType = A['name' | 'age'];
type Tuple = [string, number];
type TupleType = Tuple[number];