러닝 타입스크립트 4장
포스트
취소

러닝 타입스크립트 4장

해당 포스트는 러닝 타입스크립트 4장을 읽고 정리한 포스트입니다.
책의 모든 내용을 작성하는 것이 아닌 주관적인 기준에 따라 필요한 정보만 정리했습니다.

🎈 객체 타입

0️⃣ 객체 타입 선언

1
2
3
4
5
6
7
8
9
let myValue: {
  name: string;
  age: number;
};

myValue = {
  name: "Aatrox",
  age: 26,
};

1️⃣ 객체 타입 별칭

1
2
3
4
5
6
7
8
9
10
11
type MyValue = {
  name: string;
  age: number;
};

let myValue: MyValue;

myValue = {
  name: "Aatrox",
  age: 26,
};

🦆 구조적 타이핑

타입을 충족하면 값이 추가적으로 있어도 사용할 수 있는 것을 의미합니다.
( 조금 더 자세한 예시를 보고 싶다면 여기에서 확인해주세요! )

(1)(2)처럼 타입과 완벽하게 일치하지 않는 값을 대입해도 문제 없이 동작합니다.

1
2
3
4
5
6
7
8
9
10
11
12
type FirstName = { firstName: string };
type LastName = { lastName: string };

const fullName = {
  firstName: "a",
  lastName: "b",
};

// (1)
let firstName: FirstName = fullName;
// (2)
let lastName: LastName = fullName;
  • 덕 타이핑: 런타임에서 사용될 때까지 객체 타입을 검사하지 않는 것을 의미 ( JavaScript )
  • 구조적 타이핑: 정적 시스템이 타입을 검사하는 것을 의미 ( TypeScript )

0️⃣ 사용 검사

객체 타입에 정의한 값을 필수적으로 선언해야 합니다. ( (1) )
또한 타입의 정보와도 일치해야 합니다. ( (2) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type Person = {
  name: string;
  age: number;
};

// (1) Error: Property 'age' is missing in type '{ name: string; }' but required in type 'Person'
const person: Person = {
  name: "Aatrox",
};

// (2) Error: Type 'string' is not assignable to type 'number'
const person: Person = {
  name: "Aatrox",
  age: "10",
};

1️⃣ 초과 속성 검사

정해진 타입보다 더 많은 속성을 부여하면 타입 오류가 발생합니다. ( (3) )
하지만 객체 리터럴이 아닌 경우에는 구조적 타이핑에 의해서 오류가 발생하지 않습니다. ( (4) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type Person = {
  name: string;
  age: number;
};

// (3)
const person1: Person = {
  name: "Aatrox",
  age: 10,

  // Error: Type '{ name: string; age: number; gender: boolean; }' is not assignable to type 'Person'.
  // Error: Object literal may only specify known properties, and 'gender' does not exist in type 'Person
  gender: true,
};

// (4)
const person = {
  name: "Aatrox",
  age: 26,
  gender: true,
};
// (4)
const person2: Person = person;

// Error: Property 'gender' does not exist on type 'Person'.
person2.gender;

2️⃣ 중첩된 객체 타입

객체의 속성으로 타입을 사용할 수 있기 때문에 (5)처럼 사용하는 것보다는 (6)처럼 사용하는 것이 더 좋습니다.
가독성도 더 좋고, 오류 메시지도 더 명확해집니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Vision = {
  left: number;
  right: number;
};

// (5)
type Person1 = {
  name: string;
  age: number;
  vision: {
    left: number;
    right: number;
  };
};

// (6)
type Person2 = {
  name: string;
  age: number;
  vision: Vision;
};

3️⃣ 선택적 속성

?:을 이용해서 선택적 속성을 부여할 수 있습니다.
선택적 속성은 존재하지 않아도 되고 undefined를 넣어줘도 됩니다. ( (7) )
하지만 undefined를 유니언으로 선언했다면 속성 값을 반드시 선언해줘야합니다. ( (8) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
type Person = {
  name: string;
  age?: number;
  gender: boolean | undefined;
};
/**
 * type Person = {
 *   name: string;
 *   age?: number | undefined;
 *   gender: boolean | undefined;
 * }
 */ 

// (7)
const person1: Person = {
  name: "Aatrox",
  age: 26,
  gender: false,
};

// (8) Error: Property 'gender' is missing in type '{ name: string; age: number; }' but required in type 'Person'
const person2: Person = {
  name: "Aatrox",
  age: 26,
};

// (7) 문제 없음
const person3: Person = {
  name: "Aatrox",
  gender: false,
};

// (8) "undefined"라도 반드시 선언해줘야 함
const person4: Person = {
  name: "Aatrox",
  age: 26,
  gender: undefined;
};

🌌 객체 타입 유니온

0️⃣ 유추된 객체 타입 유니온

여러 가지 객체가 될 수 있는 초깃값을 할당하면 객체들의 유니온 타입으로 추론합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const person =
  Math.random() > 0.5 ? { name: "AA", age: 2 } : { name: "BB", gender: true };
/**
  * const person: {
  *   name: string;
  *   age: number;
  *   gender?: undefined;
  * } | {
  *   name: string;
  *   gender: boolean;
  *   age?: undefined;
  * }
  */

person.name;
person.gender;
person.age;

1️⃣ 명시된 객체 타입 유니온과 객체 타입 내로잉

값의 타입이 객체 타입인 유니온이라면 일반적으로는 모든 유니온에 존재하는 값만 사용할 수 있습니다. ((1))

하지만 타입 내로잉을 사용하면 특정 객체 타입으로 좁혀서 정확하게 타입을 추론하고 사용할 수 있습니다.((2))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type Person1 = {
  name: string;
  age: number;
};
type Person2 = {
  name: string;
  gender: boolean;
};

let person: Person1 | Person2;

person =
  Math.random() > 0.5 ? { name: "AA", age: 2 } : { name: "BB", gender: true };

// (1)
person.name;
// Error: Property 'age' does not exist on type 'Person1 | Person2'.
person.age;
// Error: Property 'gender' does not exist on type 'Person1 | Person2'.
person.gender;

// (2)
if ("age" in person) {
  person.age;
} else {
  person.gender;
}

2️⃣ 판별된 유니온

판별된 유니온이란 각 객체마다 각자의 태그를 붙여서 해당 태그로 타입을 구분할 수 있도록 판별하는 것을 의미합니다.

판별된 유니온을 이용해서 타입 내로잉을 하는 것이 좋습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type Person1 = {
  type: "person1";
  name: string;
  age: number;
};
type Person2 = {
  type: "person2";
  name: string;
  gender: boolean;
};

let person: Person1 | Person2;

person =
  Math.random() > 0.5
    ? { type: "person1", name: "AA", age: 2 }
    : { type: "person2", name: "BB", gender: true };

if (person.type === "person1") {
  person.age;
} else {
  person.gender;
}

🏁 교차 타입

인터섹션(&)을 이용하고 각 타입에 선언된 모든 속성의 합집합인 타입이 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Person1 = {
  name: string;
  age: number;
};
type Person2 = {
  name: string;
  gender: boolean;
};

declare const person: Person1 & Person2;

person.name;
person.age;
person.gender;

교차 타입과 판별된 유니온을 같이 사용하면 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Person1 = {
  age: number;
  type: "person1"
};
type Person2 = {
  gender: boolean;
  type: "person2"
};

declare const person: { name: string } & ( Person1 | Person2 );

// "name: string"을 가지면서 "Person1"인 경우
if(person.type === "person1")  {
  person.age;
  person.name;
}
// "name: string"을 가지면서 "Person2"인 경우
else {
  person.name;
  person.gender;
}

0️⃣ 교차 타입의 위험성

교차 타입을 잘못 사용하면 불가능한 타입인 never가 생성될 위험이 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
// type MyType = never
type MyType = number & string;

type T1 = {
  name: string;
};
type T2 = {
  name: number;
};

// T: { name: never }
type T = T1 & T2;

📮 레퍼런스

  1. « 러닝 타입스크립트 4장 » ( 조시 골드버그 지음, 고승원 옮김, 한빛미디어, 2023 )

  2. 1-blue - 판별된 유니온
  3. 1-blue - 구조적 타이핑
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

러닝 타입스크립트 3장

러닝 타입스크립트 5장