TypeScript의 유틸리티 타입에 대해 알아보자
2023년 04월 05일
INDEX
- 유틸리티 타입은 무엇일까?
- 유틸리티 타입들을 하나씩 알아보자
2-1. Partial<T>
2-2. Readonly<T>
2-3. Record<K,T>
2-4. Pick<T,K>
2-5. Omit<T,K>
2-6. Exclude<T,U>
2-7. Extract<T,U>
2-8. NonNullable<T>
2-9. Parameters<T>
2-10. ConstructorParameters<T>
2-11. ReturnType<T>
2-12. InstanceType<T>
2-13. Required<T>
2-14. ThisParameterType
2-15. OmitThisParameter
2-16. ThisType<T>
1. 유틸리티 타입은 무엇일까?
TypeScript에서 유틸리티 타입은 TypeScript에서 제공하는 여러 전역 유틸리티 타입으로, 일반적인 타입 변환을 쉽게 하기 위해 사용할 수 있습니다. 유틸리티 타입은 이미 정의해 놓은 타입을 변환할 때 유용하게 쓰이며, 간결한 문법으로 새로운 타입을 정의할 수 있습니다.
이렇게 들으니까 하나도 모르겠네요. 유틸리티 타입을 하나씩 살펴보면서 유틸리티 타입이 무엇인지 한번 살펴봅시다.
2. 유틸리티 타입들을 하나씩 알아보자
2-1. Partial<T>
한줄 요약 : 타입의 모든 속성을 ?(옵셔널)을 적용합니다.
Partial<T>
는 TypeScript에서 제공하는 유틸리티 타입 중 하나로, 제네릭 타입 T의 모든 속성을 선택적으로 만든 새로운 타입을 생성합니다. 이를 통해 T 타입의 모든 속성을 필수가 아닌 선택적으로 만들 수 있습니다.
예를 들어, User 인터페이스가 다음과 같다고 가정해봅시다.
interface User {
name: string;
age: number;
email: string;
}
이제 Partial<User>
를 사용하여 User 인터페이스를 선택적으로 만들어진 Partial<User>
타입으로 변환하였습니다.
type PartialUser = Partial<User>;
// PartialUser 타입: { name?: string; age?: number; email?: string; }
위 코드에서 Partial<User>
를 사용하여 User 인터페이스를 선택적으로 만들어진 PartialUser
타입으로 변환하였습니다. 이제 PartialUser 타입으로 선언된 변수는 name, age, email 속성을 선택적으로 가지고 있으므로, 빈 객체로 초기화할 수 있습니다.
const user: PartialUser = {}; // 모든 속성이 선택적으로 만들어졌습니다.
이처럼 Partial<T>
를 사용하면, 기존 타입에서 필요한 부분만 선택적으로 사용할 수 있어 유용합니다. 마치 타입에 옵셔널을 모두 적용하는듯한 효과가 나타납니다.
2-2. Readonly<T>
한줄 요약 : 타입의 모든 속성을 수정할수 없게 합니다.
TypeScript에서는 유틸리티 타입(utility type)을 제공하여 타입 선언을 간편하게 할 수 있습니다. 그리고 그 중 하나가 Readonly<T>
입니다.
Readonly<T>
는 제네릭 타입 T의 모든 속성을 읽기 전용으로 만든 새로운 타입을 생성합니다. 즉, T의 속성을 수정할 수 없는 타입으로 만듭니다.
예를 들어, 다음과 같이 Person 인터페이스가 있다고 가정해봅시다.
interface Person {
name: string;
age: number;
}
이제 Readonly<Person>
을 사용하여 Person 인터페이스를 수정할 수 없는 타입으로 만들어 봅시다.
type ReadonlyPerson = Readonly<Person>;
const person: ReadonlyPerson = { name: "John", age: 30 };
person.name = "Jane"; // 에러 발생!
위 코드에서 Readonly<Person>
을 ReadonlyPerson 타입으로 지정하고, person 변수를 이 타입으로 선언합니다. 그리고 person.name을 "Jane"으로 수정하려고 하면 에러가 발생합니다. 이는 Readonly<Person>
타입으로 지정했기 때문에 person 변수의 속성을 수정할 수 없기 때문입니다.
이처럼 Readonly<T>
를 사용하면 읽기 전용 타입을 생성할수 있습니다.
2-3. Record<K,T>
한줄 요약 : 타입의 키, 값을 모두 동일 하게 정해줍니다.
TypeScript에서 Record<K, T>
는 키(key)와 값(value)의 쌍으로 이루어진 객체를 표현하는 제네릭 타입입니다. K는 객체의 키(key) 타입을, T는 값(value)의 타입을 나타냅니다.
예를 들어, 다음과 같이 Record<K, T>
를 사용하여 Person 인터페이스를 간단하게 표현할 수 있습니다.
type Person = Record<string, any>;
const person: Person = {
name: "John",
age: 30,
gender: "male",
};
위 코드에서 Record<string, any>
를 Person 타입으로 지정하고, person 변수를 이 타입으로 선언합니다. 이제 person 변수는 name, age, gender 속성을 가지는 객체가 되며, 속성의 값은 모두 any 타입으로 지정됩니다.
Record<K, T>
는 객체를 동적으로 생성할 때 유용하게 사용될 수 있습니다. 예를 들어, 다음과 같이 Record<string, any>
를 사용하여 동적으로 객체를 생성할 수 있습니다.
function createObject(keys: string[], values: any[]): Record<string, any> {
const obj: Record<string, any> = {};
keys.forEach((key, index) => {
obj[key] = values[index];
});
return obj;
}
const obj = createObject(["name", "age", "gender"], ["John", 30, "male"]);
console.log(obj); // { name: 'John', age: 30, gender: 'male' }
위 코드에서 createObject 함수는 keys와 values 배열을 인수로 받아 Record<string, any>
타입의 객체를 반환합니다. 함수 내부에서는 keys 배열과 values 배열을 순회하면서 각각의 값을 키와 값으로 가지는 객체를 생성합니다. 이렇게 생성된 객체는 obj 변수에 할당되어 출력됩니다.
2-4. Pick<T,K>
한줄 요약 : 타입의 특정 속성을 골라 가져옵니다.
TypeScript에서 Pick<T, K>
는 타입 T에서 특정 속성만 선택하여 타입을 새로 만들어내는 유틸리티 타입입니다. K는 T에서 선택하고자 하는 속성의 이름으로 이루어진 문자열 리터럴 유니온 타입입니다.
예를 들어, 다음과 같이 Pick<T, K>
를 사용하여 Person 인터페이스에서 name과 age 속성만 선택하여 PersonNameAndAge 타입을 생성할 수 있습니다.
interface Person {
name: string;
age: number;
gender: string;
}
type PersonNameAndAge = Pick<Person, "name" | "age">;
const person: PersonNameAndAge = {
name: "John",
age: 30,
};
위 코드에서 Pick<Person, "name" | "age">
는 Person 타입에서 name과 age 속성만 선택하여 새로운 타입 PersonNameAndAge를 만듭니다. 이제 PersonNameAndAge 타입을 이용하여 person 변수를 선언하면 name과 age 속성만을 가지는 객체가 됩니다.
2-5. Omit<T,K>
한줄 요약 : 타입의 특정 속성을 제거한 타입을 생성합니다..
Omit
은 TypeScript에서 제공하는 유틸리티 타입 중 하나입니다. 이 타입은 기존 타입에서
특정 속성을 제거한 새로운 타입을 생성하는 역할을 합니다.
Omit 타입은 다음과 같은 형태로 사용합니다.
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
- T: 기존 타입
- K: 제거할 속성 이름
예를 들어, 다음과 같은 Person 인터페이스가 있다고 가정해보겠습니다.
interface Person {
name: string;
age: number;
gender: string;
}
이제 Person 인터페이스에서 age 속성을 제거하고 싶다면, 다음과 같이 Omit을 사용할 수 있습니다.
type PersonWithoutAge = Omit<Person, "age">;
위의 코드에서 PersonWithoutAge 타입은 다음과 같이 정의됩니다.
type PersonWithoutAge = {
name: string;
gender: string;
};
Omit 타입은 기존 타입에서 여러 개의 속성을 제거하거나, 제거할 속성 이름이 타입 안에 없는 경우도 처리할 수 있습니다.
2-6. Exclude<T,U>
한줄 요약 : 타입의 특정 속성을 제외한 타입을 만듭니다.
Exclude<T, U>
는 타입 T에서 타입 U에 할당 가능한 속성을 제외한 새로운 타입을 생성하는 제네릭 타입입니다.
즉, Exclude<T, U>
는 T 타입에서 U 타입에 할당 가능한 모든 속성을 제외한 새로운 타입을 반환합니다. 이때 T와 U는 유니온 타입이어야 합니다.
예를 들어, string | number | boolean에서 number와 boolean 타입을 제외한 타입을 생성하고 싶다면, 다음과 같이 Exclude를 사용할 수 있습니다.
type MyType = Exclude<string | number | boolean, number | boolean>;
위 코드에서 MyType은 string 타입만을 포함하는 새로운 타입이 됩니다.
2-7. Extract<T,U>
한줄 요약 : 타입의 특정 속성만을 포함한 타입을 만듭니다.
Extract<T, U>
는 타입 T에서 타입 U`에 할당 가능한 속성들만 추출하여 새로운 타입을 생성하는 제네릭 타입입니다.
즉, Extract<T, U>
는 T 타입에서 U 타입에 할당 가능한 모든 속성을 추출하여 새로운 타입을 반환합니다. 이때 T와 U는 유니온 타입이어야 합니다.
예를 들어, string | number | boolean에서 number 타입만 추출하고 싶다면, 다음과 같이 Extract를 사용할 수 있습니다.
type MyType = Extract<string | number | boolean, number>;
위 코드에서 MyType은 number 타입만을 포함하는 새로운 타입이 됩니다.
2-8. NonNullable<T>
한줄 요약 : 타입의 속성에 null과 undefined를 제외한 타입을 생성.
NonNullable<T>
는 타입 T에서 null과 undefined를 제외한 타입을 생성하는 제네릭 타입입니다.
즉, NonNullable<T>
는 T 타입에서 null과 undefined를 제외한 모든 속성을 추출하여 새로운 타입을 반환합니다.
예를 들어, string | null | undefined에서 null과 undefined를 제외한 타입을 생성하고 싶다면, 다음과 같이 NonNullable을 사용할 수 있습니다.
type MyType = NonNullable<string | null | undefined>;
위 코드에서 MyType은 string 타입만을 포함하는 새로운 타입이 됩니다.
2-9. Parameters<T>
한줄 요약 : 매개변수 타입을 추출해 배열 타입을 만듭니다.
Parameters<T>
는 함수 타입 T의 매개변수 타입들을 추출하여 배열 타입으로 만드는 제네릭 타입입니다.
즉, Parameters<T>
는 함수 타입 T의 매개변수 타입들을 추출하여 Array 타입으로 반환합니다.
예를 들어, (x: string, y: number) => void 타입에서 매개변수 타입들을 추출하여 배열 타입으로 만들고 싶다면, 다음과 같이 Parameters를 사용할 수 있습니다.
type MyType = Parameters<(x: string, y: number) => void>;
위 코드에서 MyType은 [string, number] 타입이 됩니다.
2-10. ConstructorParameters<T>
한줄 요약 : 생성자 함수의 매개변수를 추출해 튜플타입으로 만듭니다.
ConstructorParameters<T>
는 생성자 함수 타입 T의 매개변수 타입들을 추출하여 튜플 타입으로 만드는 제네릭 타입입니다.
즉, ConstructorParameters<T>
는 생성자 함수 타입 T의 매개변수 타입들을 추출하여 Tuple 타입으로 반환합니다. 이때, Tuple 타입은 배열과 유사하지만, 각 요소의 타입이 미리 지정되어 있어서 타입 안정성을 보장합니다.
예를 들어, new (x: string, y: number) => void 생성자 함수 타입에서 매개변수 타입들을 추출하여 튜플 타입으로 만들고 싶다면, 다음과 같이 ConstructorParameters를 사용할 수 있습니다.
type MyType = ConstructorParameters<new (x: string, y: number) => void>;
위 코드에서 MyType은 [string, number] 타입이 됩니다.
ConstructorParameters 타입은 TypeScript 2.8 버전에서 추가된 타입 연산자 중 하나입니다.
2-11. ReturnType<T>
한줄 요약 : 함수의 반환 값을 추출해 타입을 만듭니다.
ReturnType<T>
는 함수 타입 T의 반환 타입을 추출하는 제네릭 타입입니다.
즉, ReturnType<T>
는 함수 타입 T의 반환 타입을 추출하여 반환합니다.
예를 들어, (x: string) => number 타입에서 반환 타입을 추출하고 싶다면, 다음과 같이 ReturnType을 사용할 수 있습니다.
type MyType = ReturnType<(x: string) => number>;
위 코드에서 MyType은 number 타입이 됩니다.
ReturnType 타입은 TypeScript 2.8 버전에서 추가된 타입 연산자 중 하나입니다.
2-12. InstanceType<T>
한줄 요약 : 생성자 함수가 생성하는 인스턴스 타입을 추출합니다.
InstanceType<T>
는 생성자 함수 타입 T가 생성할 수 있는 인스턴스 타입을 추출하는 제네릭 타입입니다.
즉, InstanceType<T>
는 생성자 함수 타입 T가 생성할 수 있는 인스턴스의 타입을 추출하여 반환합니다.
예를 들어, class MyClass { x = 0; }
에서 MyClass 생성자 함수가 생성할 수 있는 인스턴스 타입을 추출하고 싶다면, 다음과 같이 InstanceType을 사용할 수 있습니다.
type MyType = InstanceType<typeof MyClass>;
위 코드에서 MyType은 클래스의 인스턴스 타입인 { x: number }
가 됩니다.
InstanceType 타입은 TypeScript 2.8 버전에서 추가된 타입 연산자 중 하나입니다.
2-13. Required<T>
한줄 요약 : 타입의 모든 속성을 필수로 만듭니다.
Required<T>
는 타입 T의 모든 속성이 undefined 또는 null이 아닌 값을 가져야 하는 타입을 생성하는 제네릭 타입입니다.
즉, Required<T>
는 타입 T의 모든 속성이 필수적으로 존재해야 하는 타입을 반환합니다.
예를 들어, 다음과 같은 인터페이스가 있다고 가정해봅시다.
interface Person {
name?: string;
age?: number;
}
위 인터페이스에서 name과 age 속성은 모두 선택적(optional)입니다. 이제 Required 타입을 사용하여 모든 속성이 필수적으로 존재해야 하는 타입을 만들어보겠습니다.
type RequiredPerson = Required<Person>;
위 코드에서 RequiredPerson은 { name: string; age: number }
타입이 됩니다. 즉, Required를 사용하여 Person 인터페이스의 모든 속성이 필수적으로 존재하는 새로운 타입을 만들었습니다.
Required 타입은 타입스크립트 2.8 버전에서 추가된 타입 연산자 중 하나입니다.
2-14. ThisParameterType
한줄 요약 : 함수 타입의 this를 추출합니다.
ThisParameterType는 함수 타입 T의 this 매개변수 타입을 추출하는 제네릭 타입입니다.
즉, ThisParameterType<T>
는 함수 타입 T의 첫 번째 매개변수(일반적으로 this 매개변수)의 타입을 추출하여 반환합니다.
예를 들어, 다음과 같은 함수 타입이 있다고 가정해봅시다.
type MyFuncType = (this: string, x: number, y: number) => number;
위 함수 타입에서 this 매개변수의 타입을 추출하고 싶다면, 다음과 같이 ThisParameterType을 사용할 수 있습니다.
type MyThisType = ThisParameterType<MyFuncType>;
위 코드에서 MyThisType은 string 타입이 됩니다. 즉, ThisParameterType를 사용하여 함수 타입 MyFuncType에서 this 매개변수의 타입을 추출하여 새로운 타입으로 만들었습니다.
ThisParameterType 타입은 타입스크립트 3.1 버전에서 추가된 타입 연산자 중 하나입니다.
2-15. OmitThisParameter
한줄 요약 : 매개변수의 this를 제거한 타입을 생성합니다.
OmitThisParameter<T>
는 함수 타입 T에서 this 매개변수를 제거한 타입을 생성하는 제네릭 타입입니다.
즉, OmitThisParameter<T>
는 함수 타입 T에서 this 매개변수를 제거한 새로운 함수 타입을 반환합니다.
예를 들어, 다음과 같은 함수 타입이 있다고 가정해봅시다.
type MyFuncType = (this: string, x: number, y: number) => number;
위 함수 타입에서 this 매개변수를 제거하고 싶다면, 다음과 같이 OmitThisParameter을 사용할 수 있습니다.
type MyNewFuncType = OmitThisParameter<MyFuncType>;
위 코드에서 MyNewFuncType은 (x: number, y: number) => number 타입이 됩니다. 즉, OmitThisParameter를 사용하여 함수 타입 MyFuncType에서 this 매개변수를 제거한 새로운 함수 타입을 만들었습니다.
OmitThisParameter 타입은 타입스크립트 3.2 버전에서 추가된 타입 연산자 중 하나입니다.
2-16. ThisType<T>
한줄 요약 : this타입을 this로 설정해줍니다.
ThisType<T>
은 객체 리터럴에서 this가 참조하는 타입을 설정하는 유용한 타입입니다. 객체 리터럴에서 this는 객체 자신을 참조합니다. ThisType<T>
을 사용하면 this가 참조하는 타입을 지정하여 객체 리터럴의 타입을 더욱 정확하게 지정할 수 있습니다.
예를 들어, 다음과 같은 코드에서 ThisType을 사용하여 this가 참조하는 타입을 MyType으로 지정할 수 있습니다.
type MyType = {
prop1: number;
prop2: string;
myMethod(this: MyType, x: number, y: number): number;
};
const myObj: MyType = {
prop1: 42,
prop2: "hello",
myMethod(this: MyType, x: number, y: number) {
return this.prop1 * x + y;
},
};
위 코드에서 myMethod 메서드의 this 매개변수 타입을 MyType으로 지정했습니다. 이렇게 하면 myMethod에서 this를 사용할 때 MyType의 프로퍼티에 접근할 수 있습니다.
하지만 ThisType을 사용하면 다음과 같이 코드를 더욱 간결하고 명확하게 작성할 수 있습니다.
type MyType = {
prop1: number;
prop2: string;
myMethod(this: this, x: number, y: number): number;
};
const myObj: MyType = {
prop1: 42,
prop2: "hello",
myMethod(this, x, y) {
return this.prop1 * x + y;
},
};
위 코드에서 myMethod 메서드의 this 매개변수 타입을 this로 지정했습니다. 이렇게 하면 ThisType이 MyType으로 자동으로 설정되어, myMethod에서 this를 사용할 때 MyType의 프로퍼티에 접근할 수 있습니다.
ThisType은 타입스크립트 2.0 버전에서 추가된 유용한 타입 중 하나입니다.
참고 문서
TypeScript Docs Utility Types