-
TypeScript 유틸리티 타입 소개JS & TS 2024. 10. 11. 14:38728x90
TypeScript는 JavaScript에 정적 타입을 더하여 코드의 안정성을 높이는 역할을 합니다.
특히 TypeScript에는 유용한 유틸리티 타입들이 있어, 코드를 작성할 때 매우 편리하게 활용할 수 있습니다.
TypeScript에서 자주 사용되는 유틸리티 타입과 기능을 소개해 보겠습니다.1. Pick<Type, Keys>
Pick
은 특정 타입에서 원하는 프로퍼티만 선택하여 새 타입을 만드는 데 유용합니다.
이 기능을 사용하면 큰 인터페이스나 객체 타입 중에서 필요한 부분만 사용하고 싶을 때 매우 편리합니다.언제 사용하나요?
- 특정 객체에서 필요한 일부 속성만 타입으로 사용하고자 할 때
사용 예시
interface User { id: number; name: string; age: number; email: string; } // User 타입에서 id와 name만 포함한 새 타입을 생성 type UserSummary = Pick<User, 'id' | 'name'>; const user: UserSummary = { id: 1, name: 'Alice', };
2. Omit<Type, Keys>
Omit
은 특정 타입에서 원하는 프로퍼티를 제외하고 새 타입을 만드는 데 사용됩니다.Pick
과는 반대로 작동하며, 타입에서 제외할 속성을 지정할 수 있습니다.언제 사용하나요?
- 객체 타입에서 특정 프로퍼티만 제거하고 싶을 때
사용 예시
interface User { id: number; name: string; age: number; email: string; } // User 타입에서 email을 제외한 새 타입을 생성 type UserWithoutEmail = Omit<User, 'email'>; const user: UserWithoutEmail = { id: 1, name: 'Alice', age: 25, };
3. Partial
Partial
은 특정 타입의 모든 프로퍼티를 선택적으로 만듭니다.
주로 객체의 일부만 업데이트할 때 유용합니다.언제 사용하나요?
- 객체를 부분적으로 업데이트하거나 초기 값을 설정할 때
사용 예시
interface User { id: number; name: string; age: number; email: string; }; type OptionalUser = Partial<User> // 모든 속성이 선택적임 const updateUser: OptionalUser = { name: 'Bob', };
4. Required
Required
는 특정 타입의 모든 프로퍼티를 필수로 만듭니다.Partial
의 반대 기능을 한다고 볼 수 있습니다.언제 사용하나요?
- 객체의 모든 속성이 반드시 필요할 때
사용 예시
interface User { id?: number; name?: string; age?: number; } // 모든 속성이 필수로 바뀜 type CompleteUser = Required<User>;
5. Readonly
Readonly
는 특정 타입의 모든 프로퍼티를 읽기 전용으로 만듭니다.
이 타입을 사용하면 객체의 속성을 변경할 수 없도록 제한할 수 있습니다.언제 사용하나요?
- 객체의 불변성을 유지하고 싶을 때
사용 예시
interface User { id: number; name: string; } const user: Readonly<User> = { id: 1, name: 'Alice', }; // user.id = 2; // 오류 발생: 읽기 전용 속성입니다.
6. Record<Keys, Type>
Record
는 키와 값을 정의하여 새로운 타입을 생성합니다.
주로 객체를 미리 정의된 키의 집합으로 관리하고 싶을 때 사용합니다.언제 사용하나요?
- 특정 키 집합과 그 값의 타입을 명확하게 정의하고 싶을 때
사용 예시
type CatInfo = { age: number; breed: string; }; type CatName = 'miffy' | 'boris' | 'mordred'; const cats: Record<CatName, CatInfo> = { miffy: { age: 10, breed: 'Persian' }, boris: { age: 5, breed: 'Maine Coon' }, mordred: { age: 16, breed: 'British Shorthair' } };
7. Exclude<Type, ExcludedUnion>
Exclude
는 특정 타입에서 다른 타입을 제거하여 새 타입을 만듭니다.언제 사용하나요?
- 유니온 타입에서 특정 타입을 제외하고 싶을 때
사용 예시
type Status = 'active' | 'inactive' | 'banned'; type ActiveStatus = Exclude<Status, 'banned'>; const status: ActiveStatus = 'active';
8. Extract<Type, Union>
Extract
는 특정 타입에서 지정된 타입만 추출합니다.언제 사용하나요?
- 유니온 타입에서 특정 타입만 선택하고 싶을 때
사용 예시
type Status = 'active' | 'inactive' | 'banned'; type AllowedStatus = Extract<Status, 'active' | 'inactive'>; const status: AllowedStatus = 'inactive';
9. NonNullable
NonNullable
은 특정 타입에서null
과undefined
를 제거합니다.언제 사용하나요?
- 타입에서
null
또는undefined
를 허용하지 않도록 하고 싶을 때
사용 예시
type User = { name: string | null; age?: number; }; type NonNullableUser = NonNullable<User['name']>; // string 타입만 남음
10. ReturnType
ReturnType
은 함수 타입의 반환 타입을 추출합니다.
주로 함수의 반환 타입을 다른 곳에서 재사용하고자 할 때 유용합니다.언제 사용하나요?
- 함수의 반환 타입을 따로 관리하거나 재사용하고 싶을 때
사용 예시
function getUser() { return { id: 1, name: 'Alice', }; } type User = ReturnType<typeof getUser>; const user: User = { id: 1, name: 'Alice', };
11. Parameters
Parameters
는 함수 타입의 매개변수 타입을 튜플로 반환합니다.언제 사용하나요?
- 함수의 매개변수 타입을 다른 함수에서 재사용하고 싶을 때
사용 예시
function add(a: number, b: number): number { return a + b; } type AddParams = Parameters<typeof add>; // [number, number] const args: AddParams = [3, 5]; const result = add(...args);
커스텀 유틸리티 타입
내장된 유틸리티 타입 외에도 자주 사용하는 커스텀 유틸리티 타입들이 있습니다.
다섯 가지 유용한 커스텀 유틸리티 타입을 소개합니다.1. Mutable
Readonly
의 반대로, 특정 타입의 모든 프로퍼티를 변경 가능하게 만듭니다.언제 사용하나요?
- 읽기 전용 타입을 다시 변경 가능하게 하고 싶을 때
사용 예시
type Mutable<T> = { -readonly [P in keyof T]: T[P]; }; interface ReadonlyUser { readonly id: number; readonly name: string; } type MutableUser = Mutable<ReadonlyUser>; const user: MutableUser = { id: 1, name: 'Alice', }; user.id = 2; // 정상적으로 동작
2. Nullable
특정 타입에
null
을 추가하여 허용하는 타입을 만듭니다.언제 사용하나요?
- 기존 타입에
null
을 허용하고 싶을 때
사용 예시
type Nullable<T> = T | null; interface User { id: number; name: string; } type NullableUser = Nullable<User>; const user: NullableUser = null; // 정상적으로 동작
3. OptionalKeys
특정 타입에서 선택적(
?
)인 프로퍼티의 키만 추출합니다.언제 사용하나요?
- 객체 타입에서 선택적인 프로퍼티만 추출하고 싶을 때
사용 예시
type User = { id: number; name?: string; age?: number; }; type OptionalKeys<T> = { [K in keyof T]-?: undefined extends T[K] ? K : never; }[keyof T]; type UserOptionalKeys = OptionalKeys<User>; // 'name' | 'age'
4. UnionToIntersection
유니온 타입을 인터섹션 타입으로 변환합니다.
언제 사용하나요?
- 여러 타입을 결합하여 하나의 타입으로 만들고 싶을 때
사용 예시
type UnionToIntersection<U> = (U extends any ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never; type Union = { a: string } | { b: number }; type Intersection = UnionToIntersection<Union>; // { a: string } & { b: number }
5. DeepPartial
모든 중첩된 프로퍼티를 선택적으로 만듭니다.
언제 사용하나요?
- 깊은 객체 구조에서 모든 속성을 선택적으로 만들고 싶을 때
사용 예시
type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; }; interface User { id: number; profile: { name: string; age: number; }; } type PartialUser = DeepPartial<User>; const user: PartialUser = { profile: { name: 'Alice', }, };
이처럼 TypeScript의 다양한 유틸리티 타입들과 인터페이스 관련 기능들을 사용하면 코드의 가독성과 재사용성을 높이고, 타입 안전성을 강화할 수 있습니다.
Typescript의 유틸리티 타입들을 적극 활용하고, 커스텀 유틸리티 타입을 만들어 더욱 안정적이고 유지보수가 쉬운 코드를 작성해 보세요.'JS & TS' 카테고리의 다른 글
구조분해 사용 팁 4가지 (2) 2024.09.14 Javascript ES15(ECMAScript 2024) 문법정리 (0) 2024.08.14 자바스크립트 비동기 프로그래밍 패턴 (0) 2024.05.28 Javascript ES14 문법정리 (0) 2023.12.15 Javascript ES13 문법정리 (0) 2023.12.04