- [TypeScript] Utility Type 완전 분석2025년 06월 18일 21시 39분 30초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
TypeScript Utility Type 완전 분석
TypeScript는 JavaScript에 정적 타입을 부여하여 코드의 안정성과 생산성을 향상시키는 언어이다. TypeScript의 강력한 기능 중 하나는 바로 유틸리티 타입이다. 유틸리티 타입은 기존 타입을 기반으로 새로운 타입을 쉽게 생성할 수 있도록 돕는 도구 모음이다. 이 글에서는 TypeScript의 주요 유틸리티 타입들을 상세히 알아본다.
1. 유틸리티 타입이란 무엇인가?
유틸리티 타입은 TypeScript의 내장된 제네릭 타입 함수라고 할 수 있다. 이들은 기존 타입의 속성을 변형하거나 선택적으로 추출하는 등의 작업을 통해 새로운 타입을 생성한다. 이를 통해 개발자는 반복적인 타입 정의를 줄이고, 코드의 가독성과 재사용성을 높일 수 있다.
- 코드 재사용성 증대: 이미 정의된 타입을 활용하여 새로운 타입을 만들 수 있다.
- 타입 안정성 강화: 특정 상황에 맞는 엄격한 타입 검사를 가능하게 한다.
- 생산성 향상: 복잡한 타입 정의를 간결하게 표현할 수 있다.
2. 주요 유틸리티 타입 종류
Partial<T>
Partial<T>
은 타입T
의 모든 프로퍼티를 선택적(optional)으로 만든다. 즉, 해당 타입의 모든 속성에?
를 붙인 것과 같은 효과를 낸다.- 사용 예시: 객체의 일부만 업데이트할 때 유용하다.
interface User { id: number; name: string; email: string; } type PartialUser = Partial<User>; // 결과: { id?: number; name?: string; email?: string; } const userUpdate: PartialUser = { name: "홍길동", };
Readonly<T>
Readonly<T>
는 타입T
의 모든 프로퍼티를 읽기 전용(readonly)으로 만든다. 이는 해당 프로퍼티에 값을 할당하는 것을 방지한다.- 사용 예시: 객체의 불변성을 보장해야 할 때 사용한다.
interface Product { id: number; name: string; price: number; } type ReadonlyProduct = Readonly<Product>; // 결과: { readonly id: number; readonly name: string; readonly price: number; } const product: ReadonlyProduct = { id: 1, name: "책상", price: 50000, }; // product.price = 60000; // 에러: 'price' 속성을 읽기 전용으로 설정했기 때문에 할당할 수 없다.
Pick<T, K>
Pick<T, K>
는 타입T
에서 프로퍼티K
를 선택하여 새로운 타입을 생성한다.K
는T
의 프로퍼티 키들의 유니온 타입이어야 한다.- 사용 예시: 특정 인터페이스에서 필요한 속성만 추출하여 새로운 타입을 만들 때 편리하다.
interface User { id: number; name: string; email: string; address: string; } type UserProfile = Pick<User, "name" | "email">; // 결과: { name: string; email: string; } const userProfile: UserProfile = { name: "김철수", email: "kim@example.com", };
Omit<T, K>
Omit<T, K>
는 타입T
에서 프로퍼티K
를 제외한 새로운 타입을 생성한다.K
는T
의 프로퍼티 키들의 유니온 타입이어야 한다.Pick
과 정반대의 개념이다.- 사용 예시: 기존 타입에서 특정 속성만 제외하고 싶을 때 유용하다.
interface Product { id: number; name: string; price: number; description: string; } type ProductWithoutDescription = Omit<Product, "description">; // 결과: { id: number; name: string; price: number; } const simpleProduct: ProductWithoutDescription = { id: 101, name: "노트북", price: 1200000, };
Exclude<T, U>
Exclude<T, U>
는 타입T
에서U
에 할당 가능한 모든 유니온 멤버를 제외하여 새로운 타입을 생성한다. 유니온 타입에서 특정 타입을 제거할 때 사용한다.- 사용 예시: 유니온 타입에서 특정 값을 제외한 새로운 유니온 타입을 만들 때 활용한다.
type AllColors = "red" | "green" | "blue" | "yellow"; type PrimaryColors = Exclude<AllColors, "yellow" | "green">; // 결과: "red" | "blue" const color: PrimaryColors = "red"; // const anotherColor: PrimaryColors = "yellow"; // 에러: '"yellow"' 형식은 'PrimaryColors' 형식에 할당할 수 없다.
Extract<T, U>
Extract<T, U>
는 타입T
에서U
에 할당 가능한 모든 유니온 멤버를 추출하여 새로운 타입을 생성한다.Exclude
와 정반대의 개념이다.- 사용 예시: 유니온 타입에서 특정 값을 추출하여 새로운 유니온 타입을 만들 때 사용한다.
type AllShapes = "circle" | "square" | "triangle" | 1 | 2; type GeometricShapes = Extract<AllShapes, "circle" | "square" | "triangle">; // 결과: "circle" | "square" | "triangle" const shape: GeometricShapes = "square"; // const numberShape: GeometricShapes = 1; // 에러: '1' 형식은 'GeometricShapes' 형식에 할당할 수 없다.
NonNullable<T>
NonNullable<T>
는 타입T
에서null
과undefined
를 제외한 새로운 타입을 생성한다.- 사용 예시:
null
또는undefined
가 될 수 있는 타입에서 이들을 제거하여 안전하게 타입을 다룰 때 유용하다.
type MaybeString = string | null | undefined; type SureString = NonNullable<MaybeString>; // 결과: string const text: SureString = "Hello"; // const nullText: SureString = null; // 에러: 'null' 형식은 'string' 형식에 할당할 수 없다.
Parameters<T>
Parameters<T>
는 함수 타입T
의 매개변수 타입을 튜플 형태로 추출하여 새로운 타입을 생성한다.- 사용 예시: 함수의 매개변수 타입을 동적으로 얻어와 다른 함수에서 활용할 때 유용하다.
function greet(name: string, age: number) { console.log(`안녕하세요, ${name}님! ${age}살이시군요.`); } type GreetParams = Parameters<typeof greet>; // 결과: [name: string, age: number] const params: GreetParams = ["영희", 25]; // const invalidParams: GreetParams = ["철수"]; // 에러: 'age' 인수가 필요하다.
ReturnType<T>
ReturnType<T>
는 함수 타입T
의 반환 타입(return type)을 추출하여 새로운 타입을 생성한다.- 사용 예시: 함수의 반환 타입을 기반으로 다른 타입 정의를 할 때 편리하다.
function calculateSum(a: number, b: number): number { return a + b; } type SumResult = ReturnType<typeof calculateSum>; // 결과: number const result: SumResult = calculateSum(10, 20);
Required<T>
Required<T>
는 타입T
의 모든 프로퍼티를 필수(required)로 만든다.Partial
과 반대되는 개념이다.- 사용 예시: 선택적 프로퍼티가 포함된 타입에서 모든 프로퍼티를 필수로 만들어야 할 때 유용하다.
interface Config { theme?: string; fontSize?: number; darkMode?: boolean; } type FullConfig = Required<Config>; // 결과: { theme: string; fontSize: number; darkMode: boolean; } const myConfig: FullConfig = { theme: "dark", fontSize: 16, darkMode: true, }; // const partialConfig: FullConfig = { theme: "light" }; // 에러: 'fontSize' 및 'darkMode' 속성이 없다.
Record<K, T>
Record<K, T>
는 키K
와 값T
를 가지는 객체 타입을 구성한다. 여기서K
는 유효한 프로퍼티 키(string
,number
,symbol
또는 이들의 리터럴 유니온)를 나타내고,T
는 해당 키에 할당될 값의 타입을 나타낸다.- 사용 예시: 특정 키와 값의 패턴을 가진 객체 타입을 정의할 때 유용하다.
type PagePaths = "home" | "about" | "contact"; type PageInfo = { title: string; url: string }; type Pages = Record<PagePaths, PageInfo>; /* 결과: { home: { title: string; url: string; }; about: { title: string; url: string; }; contact: { title: string; url: string; }; } */ const sitePages: Pages = { home: { title: "메인 페이지", url: "/" }, about: { title: "회사 소개", url: "/about" }, contact: { title: "문의하기", url: "/contact" }, }; // const invalidPages: Pages = { home: { title: "메인 페이지", url: "/" } }; // 에러: 'about' 및 'contact' 속성이 없다.
3. 유틸리티 타입의 활용
유틸리티 타입은 실제 개발 환경에서 다양한 방식으로 활용될 수 있다.
- API 응답 데이터 처리: API에서 받아온 데이터의 일부만 필요하거나, 특정 필드를 선택적으로 만들 때
Pick
,Partial
등을 사용할 수 있다. - 상태 관리: 애플리케이션의 상태를 정의할 때, 특정 상태 값만 업데이트해야 할 경우
Partial
을 활용하여 유연하게 처리할 수 있다. - 불변 객체 생성: 객체의 불변성을 강제해야 하는 상황에서
Readonly
를 사용하여 오류를 방지할 수 있다. - 함수 시그니처 추출: 고차 함수를 작성하거나, 함수의 매개변수와 반환 타입을 동적으로 다루어야 할 때
Parameters
와ReturnType
이 큰 도움이 된다.
TypeScript의 유틸리티 타입은 단순한 문법적 설탕을 넘어, 타입 시스템을 훨씬 강력하고 유연하게 만들어주는 핵심 기능이다. 이들을 적절히 활용하면 더욱 견고하고 유지보수하기 쉬운 코드를 작성할 수 있다.
728x90반응형'언어·프레임워크 > TypeScript' 카테고리의 다른 글
다음글이 없습니다.이전글이 없습니다.댓글