Frontend

타입스크립트 - Utility Types

취업하고싶다! 2025. 4. 2. 11:09
반응형

[타입스크립트] 유틸리티 타입

TypeScript는 공통 타입 변환을 용이하게 하기 위해 몇 가지 유틸리티 타입을 제공한다.

예를 들어 JS에서 배열을 다룰 때 for, while문이면 충분하겠지만 따로 forEach문이나 배열 생성하는 map, 배열요소를 찾는 find나 filter와 같이 배열을 다루는데 편리하게 이용가능한 루프 헬퍼 함수를 지원하듯이, 타입스크립트에서도 타입 변경을 쉽고 용이하게 하기위해 헬퍼함수처럼 Utility Type을 제공한다고 생각하면 된다.

 

유틸리티 타입을 쓰지 않더라도 기존의 인터페이스, 제네릭 등의 기본 문법으로 충분히 타입 변환이 가능하지만 유틸리티 타입을 사용하면 훨씬 더 간결한 문법으로 타입 정의가 가능할 뿐 아니라 이미 정의한 타입을 변환할 때 유용하게 쓸 수 있다.

 

유틸리티 타입은 어떤 독립적인 코드 문법이 아니다.

모두 우리가 배운 타입스크립트 문법(맵드 타입과 조건부 타입)을 이용해 유저들이 사용하기 편하라고 짜집기 한 함수이다.

남이 만들어 놓은 코드만 잘 갖다 쓰면 된다고 생각할 수 있지만, 만일 약간 변형된 타입 형태를 얻고 싶다면 반드시 직접 커스텀 해야 하는 때가 온다. 따라서 유틸리티 타입의 타입 문법 구성을 보며 어떤 문법 원칙에 의해 특정 타입의 모양을 반환하는지 연구할 필요가 있다.

 

유틸리티 타입 문법에 사용되는 맵드 타입(Mapped Types) 문법 & 조건부 타입(Conditional Types) 원리에 대한 포스팅은 아래에서 확인할 수 있다.

 

[ 조건부 타입 ]

 

타입스크립트 - Conditional Types

[타입스크립트] 조건부 타입조건부 타입(conditional type)이란 입력된 제네릭 타입에 따라 타입을 결정하는 기능을 말한다.위와 같이 조건부 타입 문법은 extends 키워드와 물음표 ? 기호를 사용하는

jiohjung-dev.tistory.com

 


유틸리티 타입이란?

타입스크립트에서 타입을 쉽게 변환할 수 있게 해준다.

ex) Partial, Pick, Omit, Required, ReturnType

 

1. Partial

Partial<T>은 T 타입의 모든 속성을 선택적(optional)으로 만드는 유틸리티 타입이다.

모든 속성이 옵셔널로 변경된 타입을 반환한다. 즉, T 타입의 모든 속성이 필수가 아니라 선택사항으로 처리된다.

예를 들어, 다음과 같이 인터페이스 Person이 있다.

interface Person {
  name: string;
  age: number;
  email: string;
}

위 Person 인터페이스를 사용하여 객체를 만들려면 name, age, email 속성이 모두 필요하다.

 

const person: Person = {
  name: "John",
  age: 30,
  email: "john@example.com",
};

Partial<T>를 사용해 Person 인터페이스의 모든 속성을 선택적으로 만들어보자.

 

type PartialPerson = Partial<Person>;

const partialPerson: PartialPerson = {
  name: "John",
  age: 30,
};

Partial<Person>을 사용하면 name, age, email 속성이 모두 필수가 아닌 선택적인 속성으로 간주된다. 따라서 partialPerson 객체는 name과 age만 가지고 있으며 email은 필수가 아니므로 생략할 수 있다.

 

Partial<T>를 사용하면 기존 타입을 확장하여 선택적인 속성을 추가하거나 일부 속성을 선택적으로 만드는 데 유용하다. 이렇게 만들어진 선택적인 속성들은 해당 속성들을 필요로 하는 함수나 객체의 매개변수로 활용될 때 유연성을 제공한다.

 


2. Readonly

Readonly<T>은 T 타입의 모든 속성을 읽기 전용(read-only)으로 만드는 유틸리티 타입이다.

interface Car {
  make: string;
  model: string;
  year: number;
}

const myCar: Readonly<Car> = {
  make: 'Toyota',
  model: 'Camry',
  year: 2023
};

myCar.make = 'Honda';  // 이렇게 작성하면 에러 발생. make 속성은 읽기 전용

여기서 Readonly<Car>는 Car 타입의 모든 속성을 읽기 전용으로 만드는 것이다. 그러므로 myCar 객체의 속성 값은 생성 시에 지정한 후에는 변경할 수 없다.

이를 통해 의도치 않은 수정을 방지하고 코드의 안정성을 높일 수 있다.

 


3. Record<K,T>

Record<K,T>속성의 타입이 K, 값의 타입이 T인 객체를 생성하는 유틸리티 타입이다.

type FruitCount = Record<string, number>;

const fruitBasket: FruitCount = {
  apple: 5,
  banana: 4,
  grape: 10,
  orange: 3
};

fruitBasket.apple; // 5
fruitBasket.grape; // 10

여기서 Record<string, number>는 속성의 타입이 string, 값의 타입이 number인 객체를 의미한다. fruitBasket은 이 타입에 따라 정의되므로 모든 속성 이름은 문자열이고 그에 해당하는 값은 숫자여야 한다. 이렇게 Record 유틸리티 타입은 동적으로 속성을 생성하고 각 속성에 특정 타입을 할당하는 데 유용하다.

 


4. Pick<T,K>

Pick<T,K>는 T에서 K 속성만 추출하여 새로운 타입을 생성하는 유틸리티 타입이다.

interface Profile {
  name: string;
  age: number;
  country: string;
}

let john: Pick<Profile, 'name' | 'age'> = {
  name: "John",
  age: 25
};

 


5. Omit<T,K>

Omit<T,K>는 T에서 K 속성을 제외한 새로운 타입을 생성하는 유틸리티 타입이다.

interface Profile {
  name: string;
  age: number;
  country: string;
}

let john: Omit<Profile, 'country'> = {
  name: "John",
  age: 25
};

 


6. Exclude<T,U>

Exclude<T,U>는 T에서 U에 해당하는 요소를 제거한 타입을 생성하는 유틸리티 타입이다.

type T = "a" | "b" | "c";
type U = Exclude<T, "a" | "b">; // "c"

 


7. Extract<T,U>

Extract<T,U>는 T에서 U에 해당하는 요소만 추출하여 새로운 타입을 생성하는 유틸리티 타입이다.

type T = "a" | "b" | "c";
type U = Extract<T, "a" | "b">; // "a" | "b"

 


8. NonNullable<T>

NonNullable<T>는 T에서 null 및 undefined를 제외한 타입을 생성하는 유틸리티 타입이다.

type T = string | number | null | undefined;
type U = NonNullable<T>; // string | number

 


9. Parameters<T>

Parameters<T>함수 T의 매개변수 타입들을 튜플 타입으로 생성하는 유틸리티 타입이다.

type T = Parameters<(a: string, b: number) => void>; // [string, number]

 


10. ReturnType<T>

ReturnType<T>함수 T의 반환 타입을 생성하는 유틸리티 타입이다.

type T = ReturnType<() => string>; // string

 


11. Required<T>

Required<T>는 T의 모든 속성을 필수적으로 만드는 유틸리티 타입이다.

interface Profile {
  name: string;
  age?: number; //옵셔널로 만들었지만 (필수로 넣을 필요가 없음)
}

let john: Required<Profile> = {
  //Required 타입으로 변환했기 때문에  age속성은 필수로 넣어야 된다.
  name: "John" // 에러! age 속성이 필요하다.
};

 

유틸리티 타입들은 TypeScript의 매우 유용한 기능 중 하나로 코드를 효율적으로 작성하고 에러를 사전에 방지하는 데 도움을 준다. 이를 잘 이해하고 사용한다면, TypeScript를 더 능숙하게 다를 수 있을 것이다.

 

 

 

 

반응형