포시코딩

1월31일 - TypeScript: Utility Type 본문

TIL

1월31일 - TypeScript: Utility Type

포시 2023. 1. 31. 15:51
728x90

개요

Enum, Generic은 자주 접하다보니 어느정도 익숙해졌는데

Utility Type이라는 새로운걸 접해서 정리해봄

 

Partial<Type>

Partial(파셜)은 특정 타입에 속해있는 집합을

모두 선택적으로 만드는 타입으로 변환

interface Toppings {
  tomatoes: boolean, 
  onion: boolean, 
  lettuce: boolean,
}

const toppingsIWant: Partial<Toppings> = {
  onion: true,
  letttuce: undefined,
  // 다른 집합은 있어도 되고 없어도 되고 undefined로 명시해줘도 됨
}

ex) 햄버거 주문 API에서 토핑을 유저가 선택적으로 주문할 수 있게 인터페이스를 만들 때 유용

 

Required<Type>

Partial의 반대. 특정 타입에 속해있는 집합을 모두 필수로 변환

interface TeaOrder {
  tea: boolean,
  straw?: boolean,
}

const myTea: Required<TeaOrder> = {
  tea: true,
  straw: true,  // 없으면 에러
}

타입을 하나 정해놓고 해당 타입을 직접 바꾸지 않고도 특정 타입의 프로퍼티들의 필수 조건들을 조작할 수 있어서

Partial과 Required는 자주 쓰이는 유틸리티 타입이다.

이렇게 타입 하나를 두고 조작을 하게 되면 여러 비슷한 타입을 새로 생성하지 않아도 된다.

 

Readonly<Type>

Readonly는 유틸리티 타입 이름 그대로 한 타입의 집합을 읽기 권한만 가능하게 변환해주는 타입.

interface BankAccount {
  accountNumber: string;
  balance: bigint;
}

const myAccount: Readonly<BankAccount> = {
  accountNumber: '1234', 
  balance: BigInt(Number.MAX_SAFE_INTEGER)
};

myAccount.accountNumber = '123'  // Error
myAccount.balance = BigInt(0)  // Error

 

Record<Keys, Type>

Record는 객체 타입을 설립하는데 쓰이는 유틸리티 타입

type Country = 'Korea' | 'USA' | 'Canada' | 'UK';  // enum도 가능
type CountryCode = 82 | 1 | 44;  // enum도 가능

type countryToCountryCode = Record<Country, CountryCode>;

const countris = {
  Korea: 82, 
  USA: 1,
  Canada: 1,
  UK: 44,
}

위에서 Record를 사용한 방법은

type countryToCountryCode = { [countryName in Country]: CountryCode };

와 같다.

 

Omit<Type, Keys>

Omit은 특정 타입에 구성되어 있는 프로퍼티를 생략할 때 사용

interface UserInfo {
  userName: string;
  favorite: string;
  email: string;
  password: string;
}

type LessUserInfo = Omit<UserInfo, 'password' | 'email'>;

const newUser: LessUserInfo = {
  userName: 'seonghun',
  favorite: 'coding',
  email: 'cchoseonghun@gmail.com', // Error
}

 

Exclude<UnionType, ExcludedMembers>

Exclude는 Union Type에 속해있는 속성들을 생략할 때 사용

type MyType = 'dog' | 'cat' | 'alpaca'
type ExcludedType = Exclude<MyType, 'cat' | 'alpaca'>

const onlyDogAllowed: ExcludedType = 'dog';
const noAlpaca: ExcludedType = 'alpaca';  // Error

직접 써서 마우스 갖다 대보면 바로 이해가능.

 

Extract<Type, Union>

Extract는 Exclude의 반대. Type에서 필요한 Union만 뽑아옴

type MyType = 'dog' | 'cat' | 'alpaca'
type ExtractedType = Extract<MyType, 'cat' | 'alpaca'>

const onlyCatOrAlpacaAllowed: ExtractedType = 'cat';  // or 'alpaca'

 

Pick<Type, Keys>

Pick은 한 Type의 특정 프로퍼티들만 뽑아 쓸 수 있도록 도와주는 Type

interface User {
  firstName: string;
  lastName: string;
}

interface Student {
  user: User;
  isGraduated: boolean;
  school: string;
}

type StudentName = Pick<Student, 'user' | 'isGraduated'>;
const studentName: StudentName = {
  user: {
    firstName: 'seonghun',
    lastName: 'cho',
  },
  isGraduated: true,
}

다른데서 import 해서 가져오는 경우 

User라는 타입은 해당 패키지에서 export하지 않고 있고

Student 타입만 export한다고 가정했을 때, Pick을 통해 user: User만 뽑아 쓸 수 있게 된다.

 

NonNullable<Type>

NonNullable은 특정 타입에서 Null 또는 Undefined Type을 생략해준다.

type QueryParam = string | string[] | undefined | null;
type NonNullableQueryParam = NonNullable<QueryParam>;

const queryParam: NonNullableQueryParam = 'orders';  // 문자열은 허용되는 타입
const forbiddenQueryParam: NonNullableQueryParam = undefined; // Error

마찬가지로 애초에 undefined나 null 없이 선언하면 되는거 아닌가? 하는 의문이 들겠지만

앞으로 사용하게될 외부 라이브러리를 가져와 쓸 때 타입에 대해 

이런 유틸리티 타입이 필요하게 될거임 ㅇㅇ

 

그 외에도 더 있다고 하지만 일단 여기까지

728x90