타입스크립트의 유틸리티 타입
이 글은 타입스크립트의 유틸리티 타입에 대해 설명합니다.
YouTube Video
타입스크립트의 유틸리티 타입
타입스크립트 유틸리티 타입은 기존 타입을 기반으로 새로운 타입을 생성하기 위한 편리한 도구입니다. 이를 통해 더 유연한 타입 정의가 가능하며 코드 재사용성을 높일 수 있습니다. 여기서는 자주 사용되는 유틸리티 타입을 자세히 설명하고, 샘플 코드를 통해 각각의 사용 방법을 논의합니다.
Partial<T>
Partial<T>
는 객체 타입의 모든 속성을 선택적으로 만듭니다 (undefined
허용). 원래 타입이 가진 일부 속성만 사용하고 싶을 때 유용합니다.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7function updateUser(user: Partial<User>) {
8 console.log(user);
9}
10
11updateUser({ name: "Alice" }); // Updates only 'name'
설명:
위의 예에서 Partial<User>
를 사용하면 User
타입의 모든 속성이 선택적으로 변경됩니다. 따라서 updateUser
함수에서 속성 중 일부만 전달할 수 있습니다.
Required<T>
Required<T>
는 선택적 속성을 포함한 모든 속성을 필수로 만듭니다. 선택적인 속성을 필수로 변환하고 싶을 때 사용됩니다.
1interface User {
2 id: number;
3 name?: string;
4 age?: number;
5}
6
7function createUser(user: Required<User>) {
8 console.log(user);
9}
10
11// createUser({ id: 1 }); // Error: 'name' and 'age' are required
12createUser({ id: 1, name: "Alice", age: 25 });
설명:
Required<User>
를 사용하면 name
및 age
와 같은 속성이 필수 속성으로 처리됩니다.
Readonly<T>
Readonly<T>
는 객체의 모든 속성을 읽기 전용으로 만듭니다. 이것은 객체의 값이 변경되지 않도록 방지합니다.
1interface User {
2 id: number;
3 name: string;
4}
5
6const user: Readonly<User> = {
7 id: 1,
8 name: "Alice"
9};
10
11// user.id = 2; // Error: 'id' is read-only
12console.log(user);
설명:
Readonly<T>
를 사용하면 객체의 속성이 변경되는 것을 방지할 수 있습니다. 개발 중 데이터가 실수로 수정되는 것을 방지하고자 할 때 효과적입니다.
Record<K, T>
Record<K, T>
는 지정된 키와 값 타입으로 맵 타입을 생성합니다. K
는 키 타입(string
또는 number
등)이고, T
는 값 타입입니다.
1type Roles = "admin" | "user" | "guest";
2interface Permissions {
3 read: boolean;
4 write: boolean;
5}
6
7const rolePermissions: Record<Roles, Permissions> = {
8 admin: { read: true, write: true },
9 user: { read: true, write: false },
10 guest: { read: false, write: false },
11};
12
13console.log(rolePermissions);
설명:
Record<K, T>
는 키-값 쌍을 정의하고자 할 때 유용합니다. 위의 예에서는 사용자 역할을 기반으로 권한이 정의됩니다.
Pick<T, K>
Pick<T, K>
는 객체 타입에서 지정된 속성만 추출합니다. 필요한 속성만 추출하여 새로운 타입을 생성할 수 있습니다.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7type UserSummary = Pick<User, "id" | "name">;
8
9const summary: UserSummary = {
10 id: 1,
11 name: "Alice"
12};
13
14console.log(summary);
설명:
Pick<T, K>
를 사용하여 객체 타입에서 특정 속성만 추출하고 이를 새로운 타입으로 처리할 수 있습니다. 예를 들어, 위의 예에서는 id
와 name
만 추출됩니다.
Omit<T, K>
Omit<T, K>
는 객체 타입에서 특정 속성을 제외합니다. 이는 Pick
의 반대 작업입니다.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5 email: string;
6}
7
8type UserWithoutEmail = Omit<User, "email">;
9
10const userWithoutEmail: UserWithoutEmail = {
11 id: 1,
12 name: "Alice",
13 age: 25
14};
15
16console.log(userWithoutEmail);
설명:
Omit<T, K>
를 사용하면 특정 속성을 제외하여 새로운 타입을 생성할 수 있습니다. 위의 예에서 email
속성이 제외됩니다.
Exclude<T, U>
Exclude<T, U>
는 유니언 타입 T
에서 타입 U
를 제거하여 새로운 타입을 만듭니다. 특정 타입을 제거하고 싶을 때 사용됩니다.
1type Status = "active" | "inactive" | "pending";
2type ExcludedStatus = Exclude<Status, "pending">;
3
4const status: ExcludedStatus = "active"; // "pending" is excluded, so it cannot be chosen
5console.log(status);
설명:
Exclude<T, U>
를 사용하면 유니언 타입 내에서 불필요한 타입을 제거할 수 있습니다. 위의 예에서 "pending"
이 제외되었기 때문에, "active"
또는 "inactive"
만 선택할 수 있습니다.
Extract<T, U>
Extract<T, U>
는 유니언 타입 T
내에서 타입 U
와 일치하는 부분을 추출합니다. 특정 타입만 추출하고 싶을 때 유용합니다.
1type Status = "active" | "inactive" | "pending";
2type ActiveStatus = Extract<Status, "active" | "pending">;
3
4const status: ActiveStatus = "active"; // "inactive" cannot be chosen
5console.log(status);
설명:
Extract<T, U>
는 Exclude
의 반대 작업을 수행합니다. 위의 예에서 "active"
와 "pending"
만 선택할 수 있습니다.
NonNullable<T>
NonNullable<T>
는 null
과 undefined
를 제외한 타입을 생성합니다. 이 값들을 선택적 타입에서 제외하고 싶을 때 유용합니다.
1type UserName = string | null | undefined;
2type ValidUserName = NonNullable<UserName>;
3
4const name: ValidUserName = "Alice"; // null and undefined cannot be chosen
5console.log(name);
설명:
NonNullable<T>
는 null
과 undefined
를 포함한 타입에서 이들을 제외합니다. 값이 확실히 존재하도록 보장하고 싶을 때 유용합니다.
결론
TypeScript 유틸리티 타입은 타입 정의를 더 간결하고 유연하게 만드는 강력한 도구입니다. Partial
, Required
, Readonly
, Record
등의 기본 유틸리티 타입을 이해하고 적절히 사용하면 코드 재사용성과 유지 관리성을 향상시킬 수 있습니다. 이 타입들을 숙달하면 더 견고하고 안전한 타입 정의를 할 수 있어 효율적인 개발이 가능합니다.
TypeScript의 keyof
연산자
TypeScript의 keyof
연산자는 객체 타입의 모든 속성 이름을 가져오는 데 사용됩니다. 이 연산자를 사용하여 객체 타입의 키를 유니온 타입으로 얻을 수 있습니다. 이는 타입 안전 코드를 작성하는 데 매우 유용합니다.
기본 사용법
1interface Person {
2 name: string;
3 age: number;
4 email: string;
5}
6
7// Use keyof to get the property names of Person
8type PersonKeys = keyof Person; // "name" | "age" | "email"
사용 예시
-
함수 인수에서 사용하기
keyof
를 사용하여 객체의 특정 속성을 기반으로 타입을 가지는 함수를 정의할 수 있습니다.
1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
2 return obj[key];
3}
4
5const person: Person = { name: "Alice", age: 30, email: "alice@example.com" };
6const name = getProperty(person, "name"); // type is string
7const age = getProperty(person, "age"); // type is number
-
타입 제약 조건 강화하기
keyof
를 사용하면 함수에 전달된 키가 컴파일 타임에 유효성을 검사하도록 할 수 있습니다.
1// Passing an invalid property name results in an error
2const invalid = getProperty(person, "invalidKey"); // Error
요약
keyof
연산자는 객체 타입의 모든 속성 이름을 가져오는 데 사용됩니다.- 속성 이름을 유니온 타입으로 가져와 타입 안전 코드를 구현할 수 있습니다.
- 함수 인수에서 이를 사용하여 함수가 유효한 속성 이름만 수락하도록 제한할 수 있습니다.
이와 같이, keyof
연산자는 TypeScript에서 타입 안전성을 강화하고 보다 견고한 코드를 작성할 수 있도록 도와줍니다.
위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.