🎉 berenickt 블로그에 온 걸 환영합니다. 🎉
Lang
TypeScript
09-유틸리티 타입(Utility Type)

1. keyof

유니온 타입을 사용한 것과 동일한 결과를 변수에 넣을 수 있음

1
interface User {
2
id: number
3
name: string
4
age: number
5
gender: 'm' | 'f'
6
}
7
8
// User 인터페이스의 키 값중 하나를 불러올 때 사용
9
type UserKey = keyof User // 'id' | 'name' | 'age' | 'gender'
10
11
const uk: UserKey = 'id'
12
13
// 다음처럼 없는 값을 넣으면 에러가 납니다.
14
// const uk: UserKey = '';

2. partial<T>

다음 코드처럼 인터페이스에 선언한 속성 값들 중 일부 속성만 넣으면 에러납니다.

1
interface User {
2
id: number
3
name: string
4
age: number
5
gender: 'm' | 'f'
6
}
7
8
// 인터페이스에 선언한 속성 값들 중 일부 속성만 넣음
9
// 💥 Error : age, gender 속성이 없음
10
let admin: User = {
11
id: 1,
12
name: '메시',
13
}

partial은 속성을 모두 Optional(선택적인) 값으로 바꿔줍니다.

1
interface User {
2
id: number
3
name: string
4
age: number
5
gender: 'm' | 'f'
6
}
7
8
// partial : 다 선택적인 속성으로 바꿔줌
9
let admin: Partial<User> = {
10
id: 1,
11
name: '메시',
12
}

3. required<T>

required는 반대로 모든 속성 값들을 필수 값으로 만들어줍니다.

1
interface User {
2
id: number
3
name: string
4
age?: number // age 속성은 선택적인 값
5
}
6
7
// Required : 모든 속성이 필수여야 함
8
// 💥 Error : age 속성이 정의안됨
9
let admin: Required<User> = {
10
id: 1,
11
name: '메시',
12
// age: 30,
13
}

age를 선언해주면 에러가 사라집니다.


4. readonly<T>

  • readonly는 말 그대로 읽기 전용으로 바꾸는 것
  • 선언만 가능하고, 수정을 할 수 없음
1
interface User {
2
id: number
3
name: string
4
age?: number
5
}
6
7
// Readonly : 읽을 수만 있음
8
let admin: Readonly<User> = {
9
id: 1,
10
name: '메시',
11
}
12
13
admin: id = 4 // 💥 Error : 수정못함

5. record<K,T>

  • record는 key와 value 값에 어떤 내용을 할당할 수 있는지 명확하게 할 때 사용
  • K는 키이고, T는 요소

다음처럼 과목별 점수를 담는 객체를 선언하면 복잡합니다.

1
interface Score {
2
'1': 'A' | 'B' | 'C' | 'D'
3
'2': 'A' | 'B' | 'C' | 'D'
4
'3': 'A' | 'B' | 'C' | 'D'
5
'4': 'A' | 'B' | 'C' | 'D'
6
}
7
8
const score: Score = {
9
1: 'A',
10
2: 'C',
11
3: 'B',
12
4: 'D',
13
}

Record를 이용하면 쉽게 표현할 수 있습니다. Record 앞에는 키, 뒤에는 요소가 들어갑니다.

1
// 1,2,3,4라는 키값에는 A,B,C,D라는 요소가 들어갈 수 있음
2
const score: Record<'1' | '2' | '3' | '4', 'A' | 'B' | 'C' | 'D'> = {
3
1: 'A',
4
2: 'C',
5
3: 'B',
6
4: 'D',
7
}

따로 변수를 만들어서 넣어두면 좀 더 편하게 사용할 수 있습니다.

1
type Grade = '1' | '2' | '3' | '4'
2
type Score = 'A' | 'B' | 'C' | 'D'
3
4
const score: Record<Grade, Score> = {
5
1: 'A',
6
2: 'C',
7
3: 'B',
8
4: 'D',
9
}

조금 더 확장해서 user객체를 받아서 이 객체가 올바른 값을 갖고 있는 지를 확인해주는 isValid라는 함수를 만든다고 합시다.

1
interface User {
2
id: number
3
name: string
4
age: number
5
}
6
7
// user 객체가 올바른 값을 가지는지 체크
8
function isValid(user: User) {
9
const result: Record<keyof User, boolean> = {
10
id: user.id > 0,
11
name: user.name !== '',
12
age: user.age > 0,
13
}
14
return result
15
}

isValid 안의 result 객체의 키값에는 id, name, age가 들어갑니다. 이 키값은 User 인터페이스의 key값과 같기 때문에 keyof User로 간단하게 사용할 수 있습니다.


6. pick<T,K>

  • T 타입에서 K 속성만 골라서 사용
1
interface User {
2
id: number
3
name: string
4
age: number
5
gender: 'M' | 'W'
6
}
7
8
// USer 인터페이스에서 id, name 속성만 사용할 떄 pick
9
const admin: Pick<User, 'id' | 'name'> = {
10
id: 0,
11
name: '메시',
12
}

7. omit<T,K>

  • pick과 반대로 T 타입에서 K 프로퍼티만 제외하고 사용할 수 있게 해 주는 키워드
  • 위 예제를 반대로 id와 name 대신 age와 gender로 바꾸고 Pick을 Omit로 바꿔주면 동일하게 동작
1
interface User {
2
id: number
3
name: string
4
age: number
5
gender: 'M' | 'W'
6
}
7
8
// USer 인터페이스에서 age, gender 속성를 제외하고 사용할 떄 omit
9
const admin: Omit<User, 'age' | 'gender'> = {
10
id: 0,
11
name: '메시',
12
}

8. exclude<T1,T2>

  • T1 타입에서 T2 타입을 제외하고 사용할 수 있게 해 주는 키워드
  • omit과 다른 점은 omit프로퍼티를 제외하는 것이고, exclude타입을 제외
  • 즉, T1타입에서 T2타입과 겹치는 것들을 제거하는 것

만약 T1 타입에서 number랑 string을 제외한 타입을 T2에 넣고 싶다면…

1
type T1 = string | number | boolean
2
type T2 = Exclude<T1, number | string> // T1 타입에서 number랑 string을 제외한 타입
3
// T2에 마우스를 올려보면, boolean 타입만 할당 가능

9. nonnullable<T>

  • null을 제외한 타입을 생성하는 키워드
  • 이름만 보면 null만 제외하는 것처럼 보일 수 있는데, undefined도 같이 제거합니다.
1
type T1 = string | null | undefined | void
2
type T2 = NonNullable<T1> // null과 undefined를 제거한 타입

Ref