TypeScript
TypeScript - Utility Type 정리
개발하길잘햇다
2021. 12. 19. 23:13
반응형
현재 내가 속한 회사에서는 개발자 모임이라는 시간을 한 달에 한 번씩 갖는다. 서로 공유하면 좋을 내용들과 개발적인 대화를 하는 매우 생산적이고 좋은 문화라고 생각하며, 이번에 그 시간을 적극적으로 활용해보기 위해 타입 스크립트에서 사용할 수 있는 유틸리티 타입에 대한 간단 소개 발표를 하게 되었다.
아래 내용은 이번 발표에 사용한 예시자료들이다.
유틸리티 타입(Utility Type)
유틸리티 타입은 이미 정의해 놓은 타입을 변환할 때 사용하기 좋은 타입 문법입니다. 유틸리티 타입을 꼭 쓰지 않더라도 기존의 인터페이스, 제네릭 등의 기본 문법으로 충분히 타입을 변환할 수 있지만 유틸리티 타입을 쓰면 훨씬 더 간결한 문법으로 타입을 정의할 수 있습니다.
Partial<T>
- 특정 타입의 부분 집합을 만족하는 타입을 정의할 수 있다.
- 옵셔널 파라미터(?)를 사용하지 않아도 에러가 발생하지 않는다.
interface Address {
email: string;
address: string;
}
type Info = Partial<Address>;
const A: Info = {}; // 가능
const B: Info = { email: 'test@test.com' }; // 가능
const C: Info = { email: 'test@test.com', address: 'Sinsa' }; // 가능
Readonly<T>
- T 의 모든 프로퍼티를 읽기 전용(readonly)으로 설정한 타입을 구성한다. 즉 생성된 타입의 프로퍼티는 재할당 할 수 없고 오직 참조만 가능하다.
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: 'Delete inactive users',
};
todo.title = 'Hello'; // 오류: 읽기 전용 프로퍼티에 재할당할 수 없음
Record<K, T>
- K 타입을 key값으로, T 타입을 value 값으로 갖는 형태의 타입을 생성한다. ex : [ K ] : T
- 주로 K에 유니온 문자열 값을 주어 map 형식의 타입을 만들 수 있고 여러 값들을 원하는 키값에 따라 분류할 때 유용하다.
interface Car {
name: string,
price: number
}
const productList: Record<"SONATA" | "AVANTE", Car> = {
SONATA: {name: "SONATA", price: 10000},
AVANTE: {name: "SONATA", price: 10000}
}
const nextProductList: Record<string, Car> = {
SONATA: {name: "SONATA", price: 10000},
AVANTE1: {name: "SONATA", price: 10000},
AVANTE2: {name: "SONATA", price: 10000},
AVANTE3: {name: "SONATA", price: 10000},
}
Pick<T, K>
- 특정 타입에서 몇 개의 속성을 선택(pick)하여 타입을 정의할 수 있습니다.
- Pick<대상타입, 선택할 속성>
interface BurgerSet {
burger: string;
potatoChip: string;
beverage: string;
}
const burgerSingle: Pick<BurgerSet, 'burger'> = {
burger: '치즈버거 단품',
};
// 두개 이상 사용시
const burgerKing: Pick<BergerSet, 'burger'|'beberage'> = {
burger: '와퍼 단품',
beverage: '코카콜라'
};
Omit<T, K>
- 특정 타입에서 지정된 속성만 제거한 타입을 정의해 줍니다.
- Omit<대상타입, 뺄속성>
interface AddressBook {
name: string;
phone: number;
address: string;
company: string;
}
const phoneBook: Omit<AddressBook, 'address'> = {
name: '재택근무',
phone: 010-1111-2222
company: '내 방'
}
// 두개이상 지정할때
const chingtao: Omit<AddressBook, 'address'|'company'> = {
name: '중국집',
phone: 02-111-8888
}
Exclude<T, U>
- T 타입들 중 U타입들과 겹치는 타입을 제외합니다.
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number
type ABC = "A" | "B" | 13
type A0 = Exclude<ABC , string> ; // 13
Extract<T, U>
- T타입에서 U 타입과 겹치는 타입만을 가져옵니다.
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
type ABC = "A" | "B" | 13
type A0 = Extract<ABC , string> ; // "A" | "B"
NonNullable<T>
- T 타입에서 Null or undefined 를 제외하고 리턴합니다.
type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
Parameters<T>
- 함수의 파라미터를 튜플[] 타입으로 리턴합니다.
function f1(arg: { a: number, b: string }): void
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
type T2 = Parameters<(<T>(arg: T) => T)>; // [unknown]
type T4 = Parameters<typeof f1>; // [{ a: number, b: string }]
type T5 = Parameters<any>; // unknown[]
type T6 = Parameters<never>; // any
// never는 any를 제외한 모든 타입의 원시타입이기때문에
// 함수타입 T에 never로 주어도 에러가 발생하지 않고
// 인자값으로도 어떠한 값이든 올 수 있기때문에 any가 리턴됩니다.
// 함수형태가 아닌 타입이 T 자리에 오면 에러가 발생합니다.
type T7 = Parameters<string>; // Error
type T8 = Parameters<Function>; // Error
//활용
const myName: T1 = ["joo"]
const myProfile : T4 = [{a: '13', b:'나이'}]
ConstructorParameters<T>
- 생성자 함수 타입의 모든 매개변수 타입을 추출할 수 있게 해 줍니다. 모든 매개변수 타입을 가지는 튜플 타입(T가 함수가 아닌 경우 never)을 생성합니다.
// 예제 1
type T0 = ConstructorParameters<ErrorConstructor>; // [(string | undefined)?]
type T1 = ConstructorParameters<FunctionConstructor>; // string[]
type T2 = ConstructorParameters<RegExpConstructor>; // [string, (string | undefined)?]
예제 1 보충 자료
ErrorContructor
FunctionConstructor
RegExpConstructor
// 예제 2
class Person {
private _firstname: string
private _lastname: string
constructor(firstname: string, lastname: string) {
this._firstname = firstname
this._lastname = lastname
}
}
type constructuinArgsType = ConstructorParameters<typeof Person>;
// [firstname: string, lastname: string]
let personConstructionArgs: constructuinArgsType = ['first', 'last']
ReturnType<T>
- 함수 T의 반환 타입으로 구성된 타입을 만듭니다.
declare function f1(): { a: number, b: string }
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<(<T>() => T)>; // {}
type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
type T4 = ReturnType<typeof f1>; // { a: number, b: string }
type T5 = ReturnType<any>; // any
type T6 = ReturnType<never>; // any
// never는 any를 제외한 모든 타입의 원시타입이기때문에
// 함수타입 T에 never로 주어도 에러가 발생하지 않고
// 인자값으로도 어떠한 값이든 올 수 있기때문에 any가 리턴됩니다.
type T7 = ReturnType<string>; // 오류
// 함수타입이 아님
type T8 = ReturnType<Function>; // 오류
// return값이 있는 함수형태가 아님
InstanceType<T>
- 생성자로 초기화된 인스턴스 타입을 리턴합니다.
let funTest = () => ({ a: 23, b: 33 });
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<(<T>() => T)>; // {}
type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
type T4 = ReturnType<typeof funTest>; // { a: number, b: string }
type T5 = ReturnType<any>; // any
type T6 = ReturnType<never>; // any
Required<T>
- T의 모든 프로퍼티가 필수로 설정된 타입을 구성합니다.
interface Props {
a?: number;
b?: string;
};
// 적용 전
const obj: Props = { a: 5 }; // 성공
// 적용 후
const obj2: Required<Props> = { a: 5 }; // 오류: 프로퍼티 'b'가 없습니다
참고 자료 출처
https://typescript-kr.github.io/pages/utility-types.html
TypeScript 한글 문서
TypeScript 한글 번역 문서입니다
typescript-kr.github.io
Typescript 유틸리티 클래스 파헤치기
Utility Types Docs를 중점으로
medium.com
반응형